Som du vet, er vanene våre en annen natur. Og når du først har blitt vant til å skrive
for (int i = 0; i <......)
, vil ingen del av deg måtte lære denne konstruksjonen på nytt (spesielt siden den er ganske enkel og forståelig). Men løkker brukes ofte gjentatte ganger for å utføre de samme grunnleggende operasjonene, og repetisjon er noe vi veldig gjerne vil bli kvitt. Med Java 8 har Oracle bestemt seg for å hjelpe oss med dette. Nedenfor er de 10 beste innsamlingsmetodene som vil spare deg for massevis av tid og kode.
1. Iterable.forEach(Forbruker <? Super T> handling)
Navnet taler for seg selv. Den itererer over samlingen som sendes som et argument, og utfører handlingen lambda-uttrykk for hvert av elementene.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(Predikat<? super E> filter)
Igjen, ikke noe vanskelig her. Metoden itererer over samlingen og fjerner alle elementer som samsvarerfilter
.
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 + " "));
På en enkelt linje fjerner vi fra listen alle tall større enn 5.
3. Map.forEach(BiConsumer <? super K, ? super V> handling)
MetodenforEach
fungerer ikke bare for klasser som implementerer grensesnittet Collection
, men også for 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 (K-tast, BiFunction<? Super K,? Super V,? Utvider V> remappingFunction)
Ser litt mer skremmende ut, men faktisk enkelt, som alle de forrige. Denne metoden setterkey
verdien lik resultatet av utførelse mappingFunction
. For eksempel:
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
Forfatteren av "Thinking in Java" er definitivt kul! :)
5. Map.computeIfAbsent(K-tast, funksjon <? super K, ? utvider V> mappingFunction)
Denne metoden vil legge til et nytt element tilMap
, men bare hvis den ikke allerede har et element med den nøkkelen. Den tildelte verdien vil være resultatet av å utføre mappingFunction
. Hvis et element med nøkkelen allerede eksisterer, vil det ikke bli overskrevet. Det vil rett og slett forbli som det er. La oss gå tilbake til bøkene våre og prøve en ny metode:
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));
Her er vår mappingFunction
:
public static String getHarryPotterAuthor() {
return "Joanne Rowling";
}
Og her er den nye boken:
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(K-tast, BiFunction<? super K, ? super V, ? utvider V> remappingFunction)
Her har vi samme prinsipp somMap.compute()
, men beregningene utføres kun hvis en vare med key
allerede eksisterer.
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));
Det første kallet til funksjonen gjorde ingen endringer, fordi det ikke er noen bok med tittelen "Eugene Onegin" i vår Map
. Men i den andre samtalen endret programmet forfatteren av boken "The Brothers Karamazov" til Alexander Pushkin. Produksjon:
_________________
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(Objektnøkkel, V defaultValue)
Denne metoden returnerer verdien som tilsvarerkey
. Hvis nøkkelen ikke eksisterer, returnerer den standardverdien.
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);
Dette er veldig praktisk:
Unknown author
8. Map.merge(K-tast, V-verdi, BiFunction<? super V, ? super V, ? utvider V> remappingFunction)
Jeg gadd ikke engang å prøve å beregne hvor mange linjer med kode denne metoden vil spare deg for.- Hvis
key
ikke eksisterer i dinMap
, eller hvisvalue
for denne nøkkelen ernull
, så legger metoden det beståttekey-value
paret tilMap
. - Hvis
key
det eksisterer og densvalue != null
, endrer metoden sin verdi til resultatet av utførelseremappingFunction
. - Hvis
remappingFunction
returnerernull
,key
fjernes den fra samlingen.
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));
Produksjon:
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
*beklager, Bruce*
9. Map.putIfAbsent(K-tast, V-verdi)
Tidligere, for å legge til et par til enMap
, hvis det ikke allerede var der, måtte du gjøre følgende:
Map <String, String> map = new HashMap<>();
if (map.get("Lord of the Rings") == null)
map.put("Lord of the Rings", "John Tolkien");
Nå har alt blitt mye enklere:
Map<String, String> map = new HashMap<>();
map.putIfAbsent("Lord of the Rings", "John Tolkien");
10. Map.replace og Map.replaceAll()
Sist men ikke minst.Map.replace(K key, V newValue)
erstatterkey
verdien mednewValue
, hvis en slik nøkkel eksisterer. Hvis ikke skjer det ingenting.Map.replace(K key, V oldValue, V newValue)
gjør det samme, men bare hvis gjeldende verdi forkey
er likoldValue
.Map.replaceAll(BiFunction<? super K, ? super V, ? extends V> function)
erstatter hvervalue
med resultatet av funksjon.
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
Det gikk ikke! Den nåværende verdien for nøkkelen "The Brothers Karamazov" er "Fyodor Dostoevsky", ikke "Bruce Eckel", så ingenting har endret seg.
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
Vi endret enkelt verdiene for hele Map
uten noen kompliserte konstruksjoner! PS Å bli vant til det nye er alltid vanskelig, men disse endringene er veldig bra. I alle fall er noen deler av koden min definitivt mindre som spaghetti enn før :) Lykke til med læringen!