![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
forEach
metodo funziona non solo per le classi che implementano l'
Collection
interfaccia, 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
key
il 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
key
esiste 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.
- Se
key
non esiste in your Map
, o se value
for this key lo è null
, il metodo aggiunge la key-value
coppia passata a Map
.
- Se
key
esiste ed è value != null
, allora il metodo cambia il suo valore nel risultato dell'esecuzione remappingFunction
.
- Se
remappingFunction
restituisce null
, key
viene 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.
Map.replace(K key, V newValue)
sostituisce key
il valore di con newValue
, se tale chiave esiste. In caso contrario, non accade nulla.
Map.replace(K key, V oldValue, V newValue)
fa la stessa cosa, ma solo se il valore corrente per key
è uguale a oldValue
.
Map.replaceAll(BiFunction<? super K, ? super V, ? extends V> function)
sostituisce ciascuno value
con 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
Map
senza 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!
GO TO FULL VERSION