Kolekcia v Jave pre pokročilých
Rád by som nadviazal na článok od Davida ( ArrayList). V článku sa pozrieme na kolekcie z viac praktického hľadiska. Spomeniem sa aj o rozdiele medzi Java 7 a Java 8, čo sa týka práce s kolekciami. Prevažne budem hovoriť o frameworku org.apache.commons.collections4, ktorý nám uľahčuje prácu. Je vhodné používať verziu 4.0 v Java 7.
Vo verzii 4.1 je plne Deprecated. Dôvodom je, že Java 8 obsahuje Lambda výrazy.
Opakovanie
Kolekcia je kontajner podobných objektov. Preferujte kolekcie pred poli. S kolekciami sa pracuje jednoduchšie ako s poľami.
Všeobecné metódy pre kolekcie: size (), isEmpty (), contains (), add (), remove (), Iterator () ... v Java 8: stream (), parallelStream ()
Definícia prázdnych kolekcií: Collections.EMPTY_LIST, Collections.EMPTY_MAP, Collections.EMPTY_SET
Najbežnejšie používané implementácie collection:
INTERFACE | IMPLEMENTÁCIA |
SET | HashSet |
LIST | ArrayList |
MAP | HashMap |
QUEUE | LinkedList |
DEQUE | ArrayDeque |
Pre radenie je dôležité určiť algoritmus, ktorým sa budú jednotlivé prvky kolekcie porovnávať. Existujú pre to dve rozhrania.
Rozhranie comparable, ktoré implementuje prvok v kolekcii. Dalo by sa povedať, že sa jedná o defaultný radenie objektu. Použitím hovoríte, že sa daný objekt má vždy radiť podľa daných vlastností.
// Defaultní objekt řazení public interface Comparable<T> { //výsledek: 0 rovnají se, + lexicograficky větší, - lexicograficky menší public int compareTo(T o); }
Rozhranie Comparator sa líšia v tom, že sa používa nad celou kolekciou. Dalo by povedať, že sa jedná o konkrétnu radenie v danej situácii. Porovnávajú sa dva objekty medzi sebou.
// Řazení podle pravidel public interface Comparator<T> { //výsledek: 0 rovnají se, + lexicograficky větší, - lexicograficky menší int compare(T o1, T o2); }
Potom stačí použiť Collections.sort. Collections.sort využíva na radenie radiacej algoritmus triedenie zlučovaním (n log (n)).
Príklad z praxe:
JAVA 7
public class Car implements Comparable<Car> { ... @Override public int compareTo(Car o) { return getId().compareTo(o.getId()); } } Collections.sort(initCars);
JAVA 8
Collections.sort(personList, (Person p1, Person p2) -> p1.firstName.compareTo(p2.firstName)); Collections.sort(personList, (p1, p2) -> p1.firstName.compareTo(p2.firstName)); personList.sort((p1, p2) -> p1.firstName.compareTo(p2.firstName));
Vyhľadanie
Pre vyhľadávanie sa v defaultných prípadoch používa metóda contains () alebo get (). Tieto metódy volajú metódu equals () nad daným objektom v kolekcii. Ak nemôžeme metódu equals () prepísať a jej porovnanie nám nevyhovuje, použijeme Predicate.
Predicate vykoná test na podmienku a vyberie prvky, ktoré tejto podmienke vyhovujú.
Metódy z CollectionUtils, pri ktorých možno použiť: Subtract, find, filter, filterInverse, countMatches, exists, matchesAll, select, atď.
public interface Predicate<T> { // true prvek vyhovuje podmínce; false nevyhovuje boolean evaluate(T object); }
Príklad z praxe:
JAVA 7:
public class CarOwnerPredicate implements Predicate<Car> { @Override public boolean evaluate(Car car) { return car.getOwner().equals(expected.getOwner()); } ... boolean result = CollectionUtils.exists(initCars, new CarOwnerPredicate(pepaCar)); // s využitím anonymní třídy Car currentPepaCar = CollectionUtils.find(initCars, new Predicate<Car>() { @Override public boolean evaluate(Car car) { return car.getOwner().equals(owner); } });
JAVA 8:
boolean exists = initCars.stream().anyMatch(car -> car.getOwner().equals(owner)); Car currentIgorCar = initCars.stream() .filter(car -> car.getOwner().equals(owner)) .limit(1) .findFirst() .get();
Transformácie Transformer
Existujú dva druhy transformácie. Prvý zmení vnútorné vlastnosti objektu, druhá ho transformuje na iný objekt.
Transformer je zodpovedný za transformáciu dát z jedného objektu do iného.
Dalo by sa povedať, že je to taký mapper medzi dvoma typmi. Metódy z CollectionUtils, pri ktorých možno použiť: transform, collect, transformingCollection
public interface Transformer<I, O> { O transform(I input); }
Príklad z praxe:
JAVA 7:
public class Car2TaxiTransformer implements Transformer<Car, Taxi> { @Override public Taxi transform(Car car) { Taxi dst = new Taxi(); dst.setColor(car.getColor()); ... List<Taxi> taxis = new ArrayList<>(CollectionUtils.collect(initCars, new Car2TaxiTransformer()));
JAVA 8:
List<Taxi> taxis = initCars.stream() .map(it -> { Taxi t = new Taxi(); t.setColor(it.getColor()); t.setCompany(GOVERNMENT); return t; }).collect(Collectors.toList());
Transformácie Closure
Closure slúži pre zmenu vlastností každého objektu v kolekcii
Metódy z CollectionUtils, pri ktorých možno použiť: forAllDo, forAllButLastDo
public interface Closure<T> { void execute(T input); }
Príklad z praxe:
JAVA 7
public class CarColorClosure implements Closure<Car> { @Override public void execute(Car car) { if ("yellow".equals(car.getColor())) { car.setColor("black"); } } ... CollectionUtils.forAllDo(initCars, new CarColorClosure());
JAVA 8
initCars.stream().forEach(car -> car.setColor("black"));
Otázka na záver: Aký návrhový vzor bol vo väčšine príkladov použitý? (Pr. CollectionUtils.forAllDo (initCars, new CarColorClosure ());)
Výsledok nájdete tu.
Dané príklady nájdete tiež v priloženom maven projektu. Vyskúšanie si čohokoľvek pomocou main () sa mi zdá neprogramátorské. V priloženom projekte preto nájdete príklady, ktoré si môžete overiť pomocou testov.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 86x (20.29 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Java