CodeGym /Blog Java /Random-PL /Przestań pisać pętle! 10 najlepszych praktyk dotyczących ...
John Squirrels
Poziom 41
San Francisco

Przestań pisać pętle! 10 najlepszych praktyk dotyczących pracy z kolekcjami w Javie 8

Opublikowano w grupie Random-PL
Przestań pisać pętle!  10 najlepszych praktyk dotyczących pracy z kolekcjami w Javie 8 - 1 Jak wiesz, nasze nawyki są drugą naturą. A kiedy już przyzwyczaisz się do pisania for (int i = 0; i <......), żadna część ciebie nie będzie chciała ponownie uczyć się tego konstruktu (zwłaszcza, że ​​jest on dość prosty i zrozumiały). Jednak pętle są często wielokrotnie używane do wykonywania tych samych podstawowych operacji, a powtarzanie jest czymś, czego bardzo chcielibyśmy się pozbyć. Dzięki Javie 8 firma Oracle postanowiła nam w tym pomóc. Poniżej znajduje się 10 najlepszych metod zbierania, które pozwolą Ci zaoszczędzić mnóstwo czasu i kodu.

1. Iterable.forEach(akcja Consumer <? Super T>)

Nazwa mówi sama za siebie. Iteruje po kolekcji przekazanej jako argument i wykonuje wyrażenie lambda akcji dla każdego z jej elementów.

List <Integer> numbers = new ArrayList<>(Arrays.asList(1,2,3,4,5,6,7));
 numbers.forEach(s -> System.out.print(s + " "));

1 2 3 4 5 6 7

2. Collection.removeIf(Predicate<? super E> filter)

Ponownie, nic trudnego tutaj. Metoda iteruje po kolekcji i usuwa wszystkie pasujące elementy filter.

 List <Integer> numbers = new ArrayList<>(Arrays.asList(1,2,3,4,5,6,7));
 numbers.removeIf(s -> s > 5);
 numbers.forEach(s -> System.out.print(s + " "));
W jednym wierszu usuwamy z listy wszystkie liczby większe niż 5.

3. Map.forEach(Akcja BiConsumer <? super K, ? super V>)

Metoda forEachdziała nie tylko dla klas, które implementują Collectioninterfejs, ale także dla Map.

 Map <String, String> books = new HashMap<>();
 books.put("War and Peace", "Leo Tolstoy");
 books.put("Crime and Punishment", "Fyodor Dostoevsky");
 books.put("Thinking in Java", "Bruce Eckel");
 books.put("The Brothers Karamazov", "Fyodor Dostoevsky");
 books.put("The Lord of the Rings", "John Tolkien");
 books.forEach((a,b) -> System.out.println("Book title: " + a + ". Author: "+ b));

Book title: The Brothers Karamazov. Author: Fyodor Dostoevsky
Book title: Thinking in Java. Author: Bruce Eckel
Book title: Crime and Punishment. Author: Fyodor Dostoevsky
Book title: War and Peace. Author: Leo Tolstoy
Book title: Lord of the Rings. Author: John Tolkien

4. Map.compute (klawisz K, BiFunction <? Super K, ? Super V, ? Extends V> remappingFunction)

Wygląda trochę bardziej onieśmielająco, ale w rzeczywistości jest prosty, jak wszystkie poprzednie. Ta metoda ustawia keywartość równą wynikowi wykonania mappingFunction. Na przykład:

Map <String, String> books = new HashMap<>();
books.put("War and Peace", "Leo Tolstoy");
books.put("Crime and Punishment", "Fyodor Dostoevsky");
books.put("Thinking in Java", "Bruce Eckel");
books.put("The Brothers Karamazov", "Fyodor Dostoevsky");
books.put("The Lord of the Rings", "John Tolkien");
books.forEach((a,b) -> System.out.println("Book title: " + a + ". Author: "+ b));
 
books.compute("Thinking in Java", (a,b) -> b + ", cool dude");
System.out.println("_______________________");
books.forEach((a,b) -> System.out.println("Book title: " + a + ". Author: "+ b));

Book title: The Brothers Karamazov. Author: Fyodor Dostoevsky
Book title: Thinking in Java. Author: Bruce Eckel
Book title: Crime and Punishment. Author: Fyodor Dostoevsky
Book title: War and Peace. Author: Leo Tolstoy
Book title: Lord of the Rings. Author: John Tolkien
_______________________
Book title: The Brothers Karamazov. Author: Fyodor Dostoevsky
Book title: Thinking in Java. Author: Bruce Eckel, cool dude
Book title: Crime and Punishment. Author: Fyodor Dostoevsky
Book title: War and Peace. Author: Leo Tolstoy
Book title: Lord of the Rings. Author: John Tolkien
Autor „Thinking in Java” jest zdecydowanie spoko! :)

5. Map.computeIfAbsent(klawisz K, funkcja <? super K, ? rozszerza V> mappingFunction)

Ta metoda doda nowy element do Map, ale tylko wtedy, gdy nie ma jeszcze elementu z tym kluczem. Przypisana wartość będzie wynikiem wykonania mappingFunction. Jeśli element z kluczem już istnieje, nie zostanie nadpisany. Po prostu pozostanie tak, jak jest. Wróćmy do naszych książek i wypróbujmy nową metodę:

Map <String, String> books = new HashMap<>();
books.put("War and Peace", "Leo Tolstoy");
books.put("Crime and Punishment", "Fyodor Dostoevsky");
books.put("Thinking in Java", "Bruce Eckel");
books.put("The Brothers Karamazov", "Fyodor Dostoevsky");
books.put("The Lord of the Rings", "John Tolkien");
 
books.computeIfAbsent("Harry Potter and the Prisoner of Azkaban", b -> getHarryPotterAuthor());
books.forEach((a,b) -> System.out.println("Book title: " + a + ". Author: "+ b));
Oto nasze mappingFunction:

public static String getHarryPotterAuthor() {
        return "Joanne Rowling";
    }
A oto nowa książka:

Book title: The Brothers Karamazov. Author: Fyodor Dostoevsky
Book title: Thinking in Java. Author: Bruce Eckel
Book title: Crime and Punishment. Author: Fyodor Dostoevsky
Book title: War and Peace. Author: Leo Tolstoy
Book title: Harry Potter and the Prisoner of Azkaban. Author: Joanne Rowling
Book title: Lord of the Rings. Author: John Tolkien

6. Map.computeIfPresent(klawisz K, BiFunction<?super K, ?super V,?extenss V>remappingFunction)

Tutaj mamy taką samą zasadę jak Map.compute(), ale obliczenia są wykonywane tylko wtedy, gdy element z keyjuż istnieje.

Map <String, String> books = new HashMap<>();
books.put("War and Peace", "Leo Tolstoy");
books.put("Crime and Punishment", "Fyodor Dostoevsky");
books.put("Thinking in Java", "Bruce Eckel");
books.put("The Brothers Karamazov", "Fyodor Dostoevsky");
books.put("The Lord of the Rings", "John Tolkien");
 
books.computeIfPresent("Eugene Onegin", (a,b) -> b = "Alexander Pushkin");
System.out.println("_________________");
books.forEach((a,b) -> System.out.println("Book title: " + a + ". Author: "+ b));
books.computeIfPresent("The Brothers Karamazov", (a,b) -> b = "Alexander Pushkin");
System.out.println("_________________");
books.forEach((a,b) -> System.out.println("Book title: " + a + ". Author: "+ b));
Pierwsze wywołanie funkcji nie przyniosło żadnych zmian, ponieważ w naszym Map. Ale w drugim wezwaniu program zmienił autora książki „Bracia Karamazow” na Aleksandra Puszkina. Wyjście:

_________________
Book title: The Brothers Karamazov. Author: Fyodor Dostoevsky
Book title: Thinking in Java. Author: Bruce Eckel
Book title: Crime and Punishment. Author: Fyodor Dostoevsky
Book title: War and Peace. Author: Leo Tolstoy
Book title: Lord of the Rings. Author: John Tolkien
 _________________
Book title: The Brothers Karamazov. Author: Alexander Pushkin
Book title: Thinking in Java. Author: Bruce Eckel
Book title: Crime and Punishment. Author: Fyodor Dostoevsky
Book title: War and Peace. Author: Leo Tolstoy
Book title: Lord of the Rings. Author: John Tolkien

7. Map.getOrDefault (klucz obiektu, V defaultValue)

Ta metoda zwraca wartość odpowiadającą key. Jeśli klucz nie istnieje, zwraca wartość domyślną.

Map <String, String> books = new HashMap<>();
books.put("War and Peace", "Leo Tolstoy");
books.put("Crime and Punishment", "Fyodor Dostoevsky");
books.put("Thinking in Java", "Bruce Eckel");
books.put("The Brothers Karamazov", "Fyodor Dostoevsky");
books.put("The Lord of the Rings", "John Tolkien");
 
String igor = books.getOrDefault("The Tale of Igor's Campaign", "Unknown author");
System.out.println(igor);
Jest to bardzo wygodne:

Unknown author

8. Map.merge (klawisz K, wartość V, BiFunction <? super V, ? super V, ? rozszerza V> remappingFunction)

Nawet nie zawracałem sobie głowy obliczeniem, ile linii kodu zaoszczędzi ci ta metoda.
  1. Jeśli keynie istnieje w twoim Map, lub jeśli valuedla tego klucza jest null, to metoda dodaje przekazaną key-valueparę do Map.
  2. Jeśli keyistnieje i jego value != null, to metoda zmienia swoją wartość na wynik wykonania remappingFunction.
  3. Jeśli remappingFunctionzwraca null, to keyjest usuwany z kolekcji.

Map <String, String> books = new HashMap<>();
books.put("War and Peace", "Leo Tolstoy");
books.put("Crime and Punishment", "Fyodor Dostoevsky");
books.put("Thinking in Java", "Bruce Eckel");
books.put("The Brothers Karamazov", "Fyodor Dostoevsky");
books.put("The Lord of the Rings", "John Tolkien");
 
books.merge("Thinking in Java", "Bruce Eckel", (a, b) -> b + " and some coauthor");
books.forEach((a, b) -> System.out.println("Title: " + a + ". Author: "+ b));
Wyjście:

Title: The Brothers Karamazov. Author: Fyodor Dostoevsky
Title: Thinking in Java. Author: Bruce Eckel and some coauthor
Title: Crime and Punishment. Author: Fyodor Dostoevsky
Title: War and Peace. Author: Leo Tolstoy
Title: Lord of the Rings. Author: John Tolkien
*przepraszam, Bruce*

9. Map.putIfAbsent(klawisz K, wartość V)

Wcześniej, aby dodać parę do Map, jeśli jeszcze jej tam nie było, należało wykonać następujące czynności:

Map <String, String> map = new HashMap<>();
if (map.get("Lord of the Rings") == null)
    map.put("Lord of the Rings", "John Tolkien");
Teraz wszystko stało się znacznie łatwiejsze:

Map<String, String> map = new HashMap<>();
map.putIfAbsent("Lord of the Rings", "John Tolkien");

10. Map.replace i Map.replaceAll()

Nie mniej ważny.
  1. Map.replace(K key, V newValue)zastępuje keywartość przez newValue, jeśli taki klucz istnieje. Jeśli nie, nic się nie dzieje.
  2. Map.replace(K key, V oldValue, V newValue)robi to samo, ale tylko wtedy, gdy bieżąca wartość for keyjest równa oldValue.
  3. Map.replaceAll(BiFunction<? super K, ? super V, ? extends V> function)zastępuje każdy valuewynikiem funkcji.
Na przykład:

Map <String, String> books = new HashMap<>();
books.put("War and Peace", "Leo Tolstoy");
books.put("Crime and Punishment", "Fyodor Dostoevsky");
books.put("Thinking in Java", "Bruce Eckel");
books.put("The Brothers Karamazov", "Fyodor Dostoevsky");
books.put("The Lord of the Rings", "John Tolkien");
 
books.replace("The Brothers Karamazov", "Bruce Eckel", "John Tolkien");
books.forEach((a, b) -> System.out.println("Title: " + a + ". Author: "+ b));

Title: The Brothers Karamazov. Author: Fyodor Dostoevsky
Title: Thinking in Java. Author: Bruce Eckel
Title: Crime and Punishment. Author: Fyodor Dostoevsky
Title: War and Peace. Author: Leo Tolstoy
Title: Lord of the Rings. Author: John Tolkien
To nie zadziałało! Obecna wartość klucza „Bracia Karamazow” to „Fiodor Dostojewski”, a nie „Bruce Eckel”, więc nic się nie zmieniło.

Map  books = new HashMap<>();
books.put("War and Peace", "Leo Tolstoy");
books.put("Crime and Punishment", "Fyodor Dostoevsky");
books.put("Thinking in Java", "Bruce Eckel");
books.put("The Brothers Karamazov", "Fyodor Dostoevsky");
books.put("The Lord of the Rings", "John Tolkien");
 
books.replaceAll((a,b) -> getCoolAuthor());
books.forEach((a, b) -> System.out.println("Title: " + a + ". Author: "+ b));

public static String getCoolAuthor() {
        return "Cool author";
     }

Title: The Brothers Karamazov. Author: Cool author
Title: Thinking in Java. Author: Cool author
Title: Crime and Punishment. Author: Cool author
Title: War and Peace. Author: Cool author
Title: Lord of the Rings. Author: Cool author
Z łatwością zmieniliśmy wartości dla całości Mapbez żadnych skomplikowanych konstrukcji! PS Przyzwyczajenie się do nowego jest zawsze trudne, ale te zmiany są naprawdę dobre. W każdym razie niektóre części mojego kodu zdecydowanie mniej przypominają spaghetti niż wcześniej :) Powodzenia w nauce!
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION