ArrayList szűrése

Fórumok

Sziasztok!

olyan kérdésem lenne, hogy egy arraylist-et hogyan tudok úgy megszűrni, hogy az ismétlődő tagok csak egyszer szerepeljenek. pl.

[22752986, 22752986, 22752986, 22752986, 12341064, 12341064, 12341064, 12341064]

Egy olyan listát szeretnék visszakapni ahol csak ez fog szerepelni:

[22752986, 12341064]

Tudnátok javasolni valami megoldást?

Köszönöm!

Tibi

Hozzászólások

miert Listet hasznalsz? miert nem Setet?


import java.util.HashSet;
import java.util.Set;

public class Main {
    public static void main(String[] args) {
        Set<Integer> datas = new HashSet<Integer>();
        for(int i = 0; i < 2; i++)
            for(int j = 0; j < 5; j++)
                datas.add(j);

        System.out.println(datas);
    }
}

ha meg nem tudod a mostani listat kikuszobolni (ilyenkor valami tervezesi hiba van...), akkor at tudod alakitani akar:


import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Main {
    public static void main(String[] args) {
        List<Integer> datas = new ArrayList<Integer>();
        Collections.addAll(datas, 1, 2, 2, 2, 3, 4, 4, 4, 4, 5);

        Set<Integer> filteredDatas = new HashSet(datas);

        System.out.println(filteredDatas);
    }
}

itt vigyazni kell, mert a masodik az nem egy view, tehat ha a backing list valtozik, nem fog
valtozni automatikusan a seted (a konstruktor ilyenkor masol).

Nekem lenne egy kicsit offtopik kérdésem:
Most kezdtem a javával ismerkedni és nem értem, miért jó upcastolni(asszem ez a helyes kifejezés :D) ebben a példában a set-et?


public static void main(String[] args) {
        Set datas = new HashSet();
        for(int i = 0; i < 2; i++)
            for(int j = 0; j < 5; j++)
                datas.add(j);

        System.out.println(datas);
    }

Miért nem jó a

HashSet datas = new HashSet();

?

ez nem upcastolas. nem hallottam meg ezt a kifejezest, honnan jott? :)

azert jo, mert a Set az egy interfesz, es amikor csak lehet, interfeszre programozunk konkret osztaly helyett. ez csokkenti a code fragilityt, es nagyobb jatszotered ad neked.

a HashSet implementalja a Set interfeszt - azaz az interfesz altal allitott contractot teljesiti (megtalalhato benne az osszes metodus) -, de hogy _hogyan_ az csak ra tartozik, Teged mint felhasznalot nem nagyon izgat.

itt a konkret peldakban amiket irtam lehetett volna hasznalni magat az osztalyt is az interfesz helyett - de minel hamarabb raszoksz arra, hogy interfeszekre programozol, annal jobb. [es a kodod is annal jobb lesz]

es konkret pelda:
az egyik alkalmazasunkban authentikalni kell a felhasznalokat, ami majd mysqlbol fog menni. igy nez ki a kod most:


public class AuthenticationResource {
    private final AAAProvider provider;

    public AuthenticationResource() {
        provider = new InMemoryProvider();
    }
...

jelenleg meg nincs adatbazis mogotte, igy egy sajat, "stubot" hasznalok, azaz csak odaraktam, mintha igazi lenne. ha az igazira akarok valtani eleg atirnom a konstruktorban, hogy


provider = new MySQLProvider();

a kodom tobbi reszehez pedig nem kell nyulnom.

ez nem upcastolas. nem hallottam meg ezt a kifejezest, honnan jott? :)

Ha az osztalyok hierarchiajat egy fastrukturakent kepzeljuk el, ahol az altalanosabb osztalyok vannak felul, felfele cast-olva jutunk az os osztalyhoz, lefele meg a leszarmazottakhoz...

----------------------
"ONE OF THESE DAYS I'M GOING TO CUT YOU INTO LITTLE PIECES!!!$E$%#$#%^*^"

ez a faban felfele meg lefele castolgatok ez hulyeseg, en sosem magyaraznam igy. miert castolgatna szerencsetlen in the first place?
ha castolnod kell, rossz a kod ;) [kiveve par esetet].

inkabb erdemes bevezetni a contract fogalmat, es elmagyarazni a kedves programozoknak, hogy _azert_ lehet castolni, _mert_, nem azert mert a faban fel meg lefele mesz...

En nem kezdokent olvastam vegig, es engem amugy is irrital a sok pelda. Viszont gyakran talalkozok olyan kezdokkel, akik szeretik a sok peldakodot...

Szerk: nezd meg a ket konyvet amit fent irtam.

Ismerem oket, nem kezdoknek valok, TIJ mas kategoria.

----------------------
"ONE OF THESE DAYS I'M GOING TO CUT YOU INTO LITTLE PIECES!!!$E$%#$#%^*^"

Ja, egyébként az egy tök jó dolog, ha az ember így kódol, de amikor hozzá kell nyulni egy olyan kódhoz, amit régóta sok ember fejlesztget, akkor szinte biztos, hogy nem tartotta be az emberek fele sem ezt a konvenciót. Szóval ilyenkor azért jól tud jönni, hogy az Eclipse-szel egy kattal Set-et lehet csinálni bármilyen HashSetből vagy TreeSetből:), és hiába kell a kód többi részéhez is nyúlni, nem fog sokkal tovább tartani, mintha eredetileg is az interface-t használná az adott kódrész.

Pl. mert beégeted az implementációt. Ha később át akarsz esetleg állni TreeSet-re, akkor az eredeti példában csak egy sort kell megváltoztatni:

Set datas = new TreeSet();

Szerk.: Ebben a kis példában ez talán nem olyan nagy probléma, mintha egy nagyobb programban 1000 helyen lenne HashSet Set helyett, amit végig kellene módosítani.

KisKresz

argh, teljesen megfeletkeztem rola hogy escapelni kene, a portalmotor meg lenyelte a generikus tipusparametereket.

ha olyan az interfesz/osztaly, hogy tamogatja ezeket, akkor soha ne hasznaljatok tipusparameter nelkul, ugyanis nehezebb lesz megfogni a hibakat.

tehat a fenti kod helyesen:


Set<Integer> datas = new HashSet<Integer>();

illetve ugyanigy a Listnel is.

És ha még a List rendezettsége is kell, akkor TreeSet.

kicsit hijackelem a topicot.. :)

szoval vannak String+Double parjaim (nem, nem sajat osztalyban, "csak ugy"). szeretnem ezeket mindig rendezetten tarolni, erre a ConcurrentSkipListMap* majdnem megoldas (keyek szerint rendez alapbol ugye, nekem meg valuek alapjan kene), es adott pillanatban
mindig _az aktualis_ N "legjobbat" [ami legelol van a sorrendben] kivenni, de atomic.

tobb szal frissiti az aktualis idhez tartozo erteket folyamatosan, ezert kell valami concurrent megoldas.

ki hogy irna meg gyorsan?

ps: lassu implementaciot tudok en is irni, engem most a sokszalu megoldasok erdekelnek.

*: TreeMapnak a concurrent megfeleloje.

Ha mindig csak a legjobb 10 kell, akkor a legjobb 10-et (X-et) nyilvántartó osztályt viszonylag könnyű megírni.

Attól függ mennyi String-Double párod van. Ha általános megoldás kell (nem csak a legjobb x) én talán csinálnék a pároknak egy container osztályt és 2 map-et hoznék létre, az egyiket String a másikat Double key-el. Amelyiknél kell, ott használnék SortedMap-et.

egy primitiv, amde mukodo megoldas


import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map.Entry;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

interface OptimalSelector<U, V> {
    public void update(U node, V value);
    public List<U> getBest(int n);
}

final class PrimitiveOptimalSelector<U, V extends Comparable<V>> implements OptimalSelector<U, V> {
    private final class EntryComparator implements Comparator<Entry<U, V>> {
        public int compare(Entry<U, V> left, Entry<U, V> right) {
            return left.getValue().compareTo(right.getValue());
        }
    }

    private final ConcurrentMap<U, V> f;
    private final Comparator<? super Entry<U, V>> comparator;

    public PrimitiveOptimalSelector() {
        f = new ConcurrentHashMap<U, V>();
        comparator = new EntryComparator();
    }

    public PrimitiveOptimalSelector(Comparator<? super Entry<U, V>> comparator) {
        f = new ConcurrentHashMap<U, V>();
        this.comparator = comparator;
    }

    public void update(U key, V value) {
        f.put(key, value);
    }
    
    public List<U> getBest(int n) {
        TreeSet<Entry<U, V>> s = new TreeSet<Entry<U, V>>(comparator);
        s.addAll(f.entrySet());
        
        List<U> result = new ArrayList<U>(n);
        for(Entry<U, V> e : s)
            if(result.size() < n)
                result.add(e.getKey());

        return result;
    }
}

public class Main {
    public static void main(String[] args) {
        OptimalSelector<String, Double> s = new PrimitiveOptimalSelector<String ,Double>();
        s.update("a", 1.0);
        s.update("b", 0.7);
        s.update("c", 1.2);
        s.update("d", 1.1);
        s.update("e", 0.2);
        System.out.println(s.getBest(3));
    }
}