CodeGym /Java Blog /Random-IT /Smetti di scrivere loop! Le 10 migliori pratiche per lavo...
John Squirrels
Livello 41
San Francisco

Smetti di scrivere loop! Le 10 migliori pratiche per lavorare con le raccolte in Java 8

Pubblicato nel gruppo Random-IT
Smetti di scrivere loop!  Le 10 migliori pratiche per lavorare con le raccolte in Java 8 - 1 Come sai, le nostre abitudini sono una seconda natura. E una volta che ti sei abituato a scrivere for (int i = 0; i <......), nessuna parte di te vuole dover imparare di nuovo questo costrutto (soprattutto perché è abbastanza semplice e comprensibile). Tuttavia, i loop vengono spesso utilizzati ripetutamente per eseguire le stesse operazioni di base e la ripetizione è qualcosa di cui vorremmo davvero sbarazzarci. Con Java 8, Oracle ha deciso di aiutarci a farlo. Di seguito sono riportati i 10 migliori metodi di raccolta che ti faranno risparmiare un sacco di tempo e codice.

1. Iterable.forEach (consumatore <? Super T> azione)

Il nome parla da sé. Itera sulla raccolta passata come argomento ed esegue l'espressione lambda dell'azione per ciascuno dei suoi elementi.

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 (predicato <? super E> filtro)

Ancora una volta, niente di difficile qui. Il metodo esegue un'iterazione sulla raccolta e rimuove tutti gli elementi che corrispondono a 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 + " "));
In una sola riga, stiamo rimuovendo dall'elenco tutti i numeri maggiori di 5.

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

Il forEachmetodo funziona non solo per le classi che implementano l' Collectioninterfaccia, ma anche per 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 (tasto K, BiFunction<? Super K,? Super V,? Extends V> remappingFunction)

Sembra un po' più intimidatorio, ma in realtà semplice, come tutti i precedenti. Questo metodo imposta keyil valore di uguale al risultato dell'esecuzione mappingFunction. Per esempio:

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
L'autore di "Thinking in Java" è decisamente figo! :)

5. Map.computeIfAbsent(tasto K, funzione <? super K, ? estende V> mappingFunction)

Questo metodo aggiungerà un nuovo elemento a Map, ma solo se non ha già un elemento con quella chiave. Il valore assegnato sarà il risultato dell'esecuzione del file mappingFunction. Se un elemento con la chiave esiste già, non verrà sovrascritto. Rimarrà semplicemente così com'è. Torniamo ai nostri libri e proviamo un nuovo metodo:

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));
Ecco il nostro mappingFunction:

public static String getHarryPotterAuthor() {
        return "Joanne Rowling";
    }
Ed ecco il nuovo libro:

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(tasto K, BiFunction<? super K, ? super V, ? estende V> remappingFunction)

Qui abbiamo lo stesso principio di Map.compute(), ma i calcoli vengono eseguiti solo se keyesiste già un elemento con.

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));
La prima chiamata alla funzione non ha apportato modifiche, perché non esiste un libro intitolato "Eugene Onegin" nel nostro file Map. Ma nella seconda chiamata, il programma ha cambiato l'autore del libro "I fratelli Karamazov" in Alexander Pushkin. Produzione:

_________________
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(Chiave oggetto, V defaultValue)

Questo metodo restituisce il valore corrispondente a key. Se la chiave non esiste, restituisce il valore predefinito.

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);
Questo è molto conveniente:

Unknown author

8. Map.merge (chiave K, valore V, BiFunction<? super V, ? super V, ? estende V> remappingFunction)

Non mi sono nemmeno preoccupato di provare a calcolare quante righe di codice questo metodo ti farà risparmiare.
  1. Se keynon esiste in your Map, o se valuefor this key lo è null, il metodo aggiunge la key-valuecoppia passata a Map.
  2. Se keyesiste ed è value != null, allora il metodo cambia il suo valore nel risultato dell'esecuzione remappingFunction.
  3. Se remappingFunctionrestituisce null, keyviene rimosso dalla raccolta.

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));
Produzione:

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
*scusa Bruce*

9. Map.putIfAbsent(chiave K, valore V)

In precedenza, per aggiungere una coppia a un Map, se non c'era già, dovevi fare quanto segue:

Map <String, String> map = new HashMap<>();
if (map.get("Lord of the Rings") == null)
    map.put("Lord of the Rings", "John Tolkien");
Ora tutto è diventato molto più semplice:

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

10. Map.replace e Map.replaceAll()

Ultimo, ma non per importanza.
  1. Map.replace(K key, V newValue)sostituisce keyil valore di con newValue, se tale chiave esiste. In caso contrario, non accade nulla.
  2. Map.replace(K key, V oldValue, V newValue)fa la stessa cosa, ma solo se il valore corrente per keyè uguale a oldValue.
  3. Map.replaceAll(BiFunction<? super K, ? super V, ? extends V> function)sostituisce ciascuno valuecon il risultato della funzione.
Per esempio:

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
Non ha funzionato! Il valore attuale per la chiave "The Brothers Karamazov" è "Fyodor Dostoevsky", non "Bruce Eckel", quindi non è cambiato nulla.

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
Abbiamo facilmente cambiato i valori per l'intero Mapsenza costrutti complicati! PS Abituarsi al nuovo è sempre difficile, ma questi cambiamenti sono davvero buoni. In ogni caso, alcune parti del mio codice sono decisamente meno spaghetti di prima :) Buona fortuna per l'apprendimento!
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION