...
Predicate-grensesnittet har metoden test, som tar inn et objekt av hvilken som helst type (det vil si Object) som argument, og returnerer en boolean.
Consumer-grensesnittet har metoden accept, som tar inn et objekt av hvilken som helst type type (det vil si Object) som argument, og returnerer ingenting (void).
Bruken av disse skal vi demonstrere senere.
...
Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | PersonMain.java |
---|
collapse | true |
---|
|
import java.util.ArrayList;
import java.util.List;
public class PersonMain {
List<Person> persons = new ArrayList<Person>();
public void init() {
persons.add(new Person("Ola", 10, 'M'));
persons.add(new Person("Kari", 12, 'F'));
persons.add(new Person("Per", 22, 'M'));
persons.add(new Person("Pål", 17, 'M'));
persons.add(new Person("Espen", 19, 'M'));
}
public void run() {
}
public static void main(String[] args) {
PersonMain program = new PersonMain();
program.init();
program.run();
}
} |
Eksemplene under vil være forskjellige implementasjoner av run()-metoden til PersonMain.java.
...
Å sortere med Comparator blir veldig enkelt med lambda, da Comparator-grensesnittet er funksjonelt. La oss sortere personene på navn (eksempel 1) og på alder (eksempel 2), og skrive ut resultatet etterpå:
Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Tradisjonell måte (anonym klasse) |
---|
| persons.sort(new Comparator<Person>() {
@Override
public int compare(Person a, Person b) {
return a.getName().compareTo(b.getName());
}
});
System.out.println(persons); |
| Code Block |
---|
| Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Med stream og lambda |
---|
| persons.sort((a, b) -> a.getName().compareTo(b.getName()));
System.out.println(persons); |
| Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Tradisjonell måte (anonym klasse) | Resultat |
---|
| [Espen 19 M, Kari 12 F, Ola 10 M, Per 22 M, Pål 17 M] |
|
Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Tradisjonell måte (anonym klasse) |
---|
| persons.sort(new Comparator<Person>() {
@Override
public int compare(Person a, persons.sort(new Comparator<Person>() {
@Override
public int compare(Person a, Person b) {
return a.getAge() - b.getAge();
});
System.out.println(persons); |
| Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Med stream og lambda |
---|
| persons.sort((a, b) -> a.getAge() - b.getAge());
System.out.println(persons); |
| Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Resultat |
---|
| [Ola 10 M, Kari 12 F, Pål 17 M, Espen 19 M, Per 22 M] |
|
Anchor |
---|
| comparatorvscomparable |
---|
| comparatorvscomparable |
---|
|
Comparator vs. Comparable
...
Vi begynner med et enkelt og nyttig eksempel på bruk av Predicate-grensesnittet og streams. anyMatch er en metode som tar inn en Predicate-instans og returnerer true dersom minst ett av elementene i den aktuelle streamen tilfredsstiller predikatet. For eksempel, finnes det en kvinne i lista vår? Vi skriver det ut.
Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Tradisjonell måte |
---|
| boolean womanExists = false;
for (Person p : persons) {
if (p.getGender() == 'F') {
womanExists = true;
break;
}
}
System.out.println(womanExists); |
| Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Med stream og lambda |
---|
| boolean womanExists = System.out.println(persons.stream().anyMatch(p -> p.getGender() == 'F')); |
| Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Resultat |
---|
| true |
|
Til høyre tar vi lista vår persons, kaller metoden stream() på den for å gjøre den til en stream og få tak i den innebygde anyMatch-metoden. anyMatch tar som kjent et predikatobjekt som argument, som vi definerer på lambdavis. Predicate-instansen vi oppretter får inn et Person-objekt (p) som argument (den vil bli kalla for alle elementene i lista, som er personer), og returnerer true dersom den aktuelle personens kjønn er kvinne.
...
Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Tradisjonell måte |
---|
| List<Person> overEighteen = new ArrayList<Person>();
for (Person p : persons) {
if (p.getAge() >= 18) {
overEighteen.add(p);
}
}
System.out.println(overEighteen); |
| Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Med stream og lambda |
---|
| System.out.println(persons.stream().filter(p -> p.getAge() >= 18).collect(Collectors.toList())); |
|
---|
Siden filter-funksjonen returnerer en stream, bruker vi collect for å gjøre den til en List.
Map
Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Resultat |
---|
| [Per 22 M, Espen 19 M] |
|
---|
Siden filter-funksjonen returnerer en stream, bruker vi collect for å gjøre den til en List.
Map
Map brukes Map brukes for å danne en ny liste av en annen liste, der en gitt funksjon blir kalt på alle elementene i lista. For eksempel, for å få en liste over alle aldrene til personene, vil vi kalle getAge-funksjonen på alle personene i lista, og legge aldrene i en ny liste.
Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Tradisjonell måte |
---|
| List<Integer> ages = new ArrayList<Integer>();
for (Person p : persons) {
ages.add(p.getAge());
}
System.out.println(ages); |
| Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Med stream og lambda |
---|
| System.out.println(persons.stream().map(Person::getAge).collect(Collectors.toList())); |
| | Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Resultat |
---|
| [10, 12, 22, 17, 19] |
|
---|
Map tar en instans av typen Map tar en instans av typen Functionsom argument. Du ser kanskje det doble kolonet. Det er en ny operator introdusert i Java 8 som lar en referere til en metode i seg selv, i stedet for returverdien til den metoden. Slik kan vi enkelt gi den metoden vi ønsker som argument.
...
Reduce brukes for å redusere en liste til et enkelt svar. Reduce tar en akkumulatorfunksjon (akkumulere == samle) som argument. Denne akkumulatoren tar to argument: Verdien så langt, og neste element. Reduce brukes ofte sammen med map. La oss finne totalalderen i lista vår.
Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Tradisjonell måte |
---|
| int totalAge = 0;
for (Person p : persons) {
totalAge += p.getAge();
}
System.out.println(totalAge); |
| Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Med stream og lambda |
---|
| System.out.println(persons.stream().map(Person::getAge).reduce((a, b) -> a + b).get()); |
| Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Resultat |
---|
| 80 |
|
---|
I tilfellet over er argumentet a den midlertidige summen av aldre, og b er alderen til neste person i lista. Grunnen til at vi kaller .get() på slutten er fordi reduce returnerer en objekt av typen Optional. Det er en container-type som kan inneholde et eksisterende objekt, eller null. Dersom det inneholder et faktisk objekt, vil isPresent() returnere true, og get() vil returnere verdien. Reduce kan også ta i bruk det doble kolonet. La oss finne maksimumsalderen:
Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Tradisjonell måte |
---|
| int maxAge = 0;
for (Person p : persons) {
if (p.getAge() > maxAge)
maxAge = p.getAge();
}
System.out.println(maxAge); |
| Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Med stream og lambda |
---|
| System.out.println(persons.stream().map(Person::getAge).reduce(Math::max).get()); |
| |
---|
forEach
Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Resultat |
---|
| 22 |
|
---|
forEach
forEach forEach tar inn en Consumer-instans og kaller denne instansens ene metode på alle elementene i streamen. La oss legge til et år på alle personenes alder.
Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Tradisjonell måte |
---|
| for (Person p : persons) {
p.setAge(p.getAge() + 1);
}
System.out.println(persons); |
| Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Med stream og lambda |
---|
| persons.stream().forEach(p -> p.setAge(p.getAge() + 1));
System.out.println(persons); |
| | Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Resultat |
---|
| [Ola 11 M, Kari 13 F, Per 23 M, Pål 18 M, Espen 20 M] |
|
---|
Vi kan også kombinere funksjoner på streams, for eksempel filter og Vi kan også kombinere funksjoner på streams, for eksempel filter og forEach. La oss si at vi vil, av en eller annen merkelig grunn, legge til et år på alderen til alle gutter under 18:
Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Tradisjonell måte |
---|
| for (Person p : persons) {
if (p.getAge() < 18 && p.getGender() == 'M')
p.setAge(p.getAge() + 1);
}
System.out.println(persons); |
| Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Med stream og lambda |
---|
| persons.stream()
.filter(p -> p.getAge() < 18 && p.getGender() == 'M')
.forEach(p -> p.setAge(p.getAge() + 1));
System.out.println(persons); |
| Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Resultat |
---|
| [Ola 11 M, Kari 12 F, Per 22 M, Pål 18 M, Espen 19 M] |
|
---|
Peek
Peek ligner veldig på forEach, men i stedet for å returnere void returnerer peek den resulterende streamenvoid returnerer peek den resulterende streamen. Derfor kan man skrive ut resultatet direkte, uten å gjøre som i de to eksemplene over.
Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Tradisjonell måte |
---|
| List<Person> agedPersons = new ArrayList<Person>();
for (Person p : persons) {
p.setAge(p.getAge() + 1);
agedPersons.add(p);
}
System.out.println(agedPersons); |
| Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Med stream og lambda |
---|
| System.out.println(persons.stream()
.peek(p -> p.setAge(p.getAge() + 1))
.collect(Collectors.toList())); |
| Code Block |
---|
theme | Eclipse |
---|
language | java |
---|
title | Resultat |
---|
| [Ola 11 M, Kari 13 F, Per 23 M, Pål 18 M, Espen 20 M] |
|
---|