Heim > Java > javaLernprogramm > Hauptteil

Interpretieren Sie die neuen Funktionen von Java8 – die Rolle von Lambda

零下一度
Freigeben: 2017-06-17 14:11:47
Original
1363 Leute haben es durchsucht

Wir haben lange darauf gewartet, dass Lambda das Konzept der Schließung nach Java bringt, aber wenn wir es nicht in Sammlungen verwenden, werden wir viel Wert verlieren. Das Problem der Migration bestehender Schnittstellen zum Lambda-Stil wurde durch Standardmethoden gelöst. In diesem Artikel werden wir die Batch-Datenoperationen in Java-Sammlungen eingehend analysieren und das Geheimnis des stärksten Lambda-Effekts lüften.

Wir haben lange darauf gewartet, dass Lambda das Konzept der Schließung nach Java bringt, aber wenn wir es nicht in Sammlungen verwenden, werden wir viel Wert verlieren. Das Problem der Migration vorhandener Schnittstellen zum Lambda-Stil wurde durch Standardmethoden gelöst. In diesem Artikel werden wir die Massendatenoperation (Massenoperation) in Java-Sammlungen eingehend analysieren und das Geheimnis der mächtigsten Rolle von Lambda lüften.

1. Über JSR335

JSR ist die Abkürzung für Java Specification Requests, was Java Specification Request bedeutet, die Hauptversion von Java 8 Eine Verbesserung ist Project Lambda (JSR 335), das darauf abzielt, Java einfacher für Mehrkernprozessoren zu programmieren.

2. Externe vs. interne Iteration

In der Vergangenheit konnten Java-Sammlungen keine interne Iteration ausdrücken. aber nur vorausgesetzt Es wird eine externe Iterationsmethode bereitgestellt, nämlich for oder while-Schleife .


List persons = asList(new Person("Joe"), new Person("Jim"), new Person("John"));
for (Person p : persons) {
 p.setLastName("Doe");
}
Nach dem Login kopieren

Das obige Beispiel ist unser vorheriger Ansatz, die sogenannte externe Iteration. Die Schleife ist eine feste Sequenzschleife. Wenn wir im heutigen Multi-Core-Zeitalter eine Parallelschleife durchführen möchten, müssen wir den obigen Code ändern. Wie stark die Effizienz verbessert werden kann, ist noch ungewiss und birgt bestimmte Risiken (Probleme mit der Thread-Sicherheit usw.).

Um die interne Iteration zu beschreiben, müssen wir eine Klassenbibliothek wie Lambda verwenden.forEach um die obige Schleife neu zu schreiben


persons.forEach(p->p.setLastName("Doe"));
Nach dem Login kopieren

Jetzt steuert die JDK-Bibliothek die Schleife. Wir müssen uns nicht darum kümmern, wie der Nachname für jedes Personenobjekt festgelegt wird. Die Bibliothek kann basierend darauf entscheiden, wie dies geschieht Führen Sie dies parallel, außer Betrieb oder verzögertes Laden aus. Dies ist eine interne Iteration und der Client übergibt das Verhalten p.setLastName als Daten an die API. Tatsächlich ist die interne Iteration nicht eng mit der Stapeloperation von Sammlungen verbunden. Dadurch können wir die Änderungen im grammatikalischen Ausdruck spüren. Das wirklich Interessante an Batch-Operationen ist die neue Stream-API. Das neue Paket java.util.stream wurde zu JDK 8 hinzugefügt.

3. Stream-API

Stream stellt nur einen Datenstrom dar und hat keine Datenstruktur, daher wurde er durchlaufen nicht mehr nach einem Mal durchlaufen werden (dies muss beim Programmieren beachtet werden, im Gegensatz zur Sammlung sind immer noch Daten darin, egal wie oft sie durchlaufen werden). Die Quelle kann Sammlung, Array, io usw. sein.

3.1 Zwischen- und Endpunktmethoden

Die Stream-Funktion bietet eine Schnittstelle für den Betrieb von Big Data und ermöglicht Daten Operationen einfacher und schneller. Es gibt Methoden wie Filtern, Zuordnen und Reduzieren der Anzahl von Durchläufen. Diese Methoden sind in zwei Typen unterteilt: Zwischenmethoden und Terminalmethoden. Die „Stream“-Abstraktion sollte von Natur aus kontinuierlich sein Wir möchten das Endergebnis erhalten. Wenn ja, muss eine Endpunktoperation verwendet werden, um das vom Stream erzeugte Endergebnis zu sammeln. Der Unterschied zwischen diesen beiden Methoden besteht darin, dass sie sich den Rückgabewert ansehen. Wenn es sich um einen Stream handelt, handelt es sich um eine Zwischenmethode, andernfalls handelt es sich um eine Endmethode.

Eine kurze Einführung in mehrere Zwischenmethoden (Filter, Karte) und Endpunktmethoden (Sammeln, Summe)

3.1.1Filter

Die Implementierung der Filterfunktion im Datenstrom ist der natürlichste Vorgang, den wir uns vorstellen können. Die Stream-Schnittstelle stellt eine Filtermethode bereit, die eine Predicate-Implementierung akzeptieren kann, die eine Operation zur Verwendung eines LambdaAusdrucks darstellt, der Filterbedingungen definiert.


List persons = …
Stream personsOver18 = persons.stream().filter(p -> p.getAge() > 18);//过滤18岁以上的人
Nach dem Login kopieren

3.1.2Map

Angenommen, wir filtern jetzt einige Daten, beispielsweise beim Konvertieren von Objekten. Mit der Map-Operation können wir eine Implementierung einer Funktion ausführen (das generische T und R von Function stellen die Ausführungseingabe bzw. das Ausführungsergebnis dar), die Eingabeparameter akzeptiert und zurückgibt. Sehen wir uns zunächst an, wie man sie als anonyme innere Klasse beschreibt:


Stream adult= persons
    .stream()
    .filter(p -> p.getAge() > 18)
    .map(new Function() {
     @Override
     public Adult apply(Person person) {
      return new Adult(person);//将大于18岁的人转为成年人
     }
    });
Nach dem Login kopieren

Konvertieren Sie nun das obige Beispiel in einen Lambda-Ausdruck:


Stream map = persons.stream()
     .filter(p -> p.getAge() > 18)
     .map(person -> new Adult(person));
Nach dem Login kopieren

3.1.3Count

Die Zählmethode ist die Endpunktmethode eines Streams, die verwendet werden kann Das Finale Statistiken der Flussergebnisse werden an int zurückgegeben. Berechnen wir beispielsweise die Gesamtzahl der Personen ab 18 Jahren


int countOfAdult=persons.stream()
      .filter(p -> p.getAge() > 18)
      .map(person -> new Adult(person))
      .count();
Nach dem Login kopieren

3.1.4Collect

Die Sammelmethode ist auch eine Endpunktmethode des Streams, die die Endergebnisse sammeln kann


List adultList= persons.stream()
      .filter(p -> p.getAge() > 18)
      .map(person -> new Adult(person))
      .collect(Collectors.toList());
Nach dem Login kopieren

Oder wenn wir eine bestimmte Implementierungsklasse verwenden möchten, um Ergebnisse zu sammeln:


List adultList = persons
     .stream()
     .filter(p -> p.getAge() > 18)
     .map(person -> new Adult(person))
     .collect(Collectors.toCollection(ArrayList::new));
Nach dem Login kopieren

篇幅有限,其他的中间方法和终点方法就不一一介绍了,看了上面几个例子,大家明白这两种方法的区别即可,后面可根据需求来决定使用。

3.2顺序流与并行流

每个Stream都有两种模式:顺序执行和并行执行。

顺序流:


List <Person> people = list.getStream.collect(Collectors.toList());
Nach dem Login kopieren

并行流:


List <Person> people = list.getStream.parallel().collect(Collectors.toList());
Nach dem Login kopieren

顾名思义,当使用顺序方式去遍历时,每个item读完后再读下一个item。而使用并行去遍历时,数组会被分成多个段,其中每一个都在不同的线程中处理,然后将结果一起输出。

3.2.1并行流原理:


List originalList = someData;
split1 = originalList(0, mid);//将数据分小部分
split2 = originalList(mid,end);
new Runnable(split1.process());//小部分执行操作
new Runnable(split2.process());
List revisedList = split1 + split2;//将结果合并
Nach dem Login kopieren

大家对hadoop有稍微了解就知道,里面的 MapReduce 本身就是用于并行处理大数据集的软件框架,其 处理大数据的核心思想就是大而化小,分配到不同机器去运行map,最终通过reduce将所有机器的结果结合起来得到一个最终结果,与MapReduce不同,Stream则是利用多核技术可将大数据通过多核并行处理,而MapReduce则可以分布式的。

3.2.2顺序与并行性能测试对比

如果是多核机器,理论上并行流则会比顺序流快上一倍,下面是测试代码


long t0 = System.nanoTime();

  //初始化一个范围100万整数流,求能被2整除的数字,toArray()是终点方法

  int a[]=IntStream.range(0, 1_000_000).filter(p -> p % 2==0).toArray();

  long t1 = System.nanoTime();

  //和上面功能一样,这里是用并行流来计算

  int b[]=IntStream.range(0, 1_000_000).parallel().filter(p -> p % 2==0).toArray();

  long t2 = System.nanoTime();

  //我本机的结果是serial: 0.06s, parallel 0.02s,证明并行流确实比顺序流快

  System.out.printf("serial: %.2fs, parallel %.2fs%n", (t1 - t0) * 1e-9, (t2 - t1) * 1e-9);
Nach dem Login kopieren

3.3关于Folk/Join框架

应用硬件的并行性在java 7就有了,那就是 java.util.concurrent 包的新增功能之一是一个 fork-join 风格的并行分解框架,同样也很强大高效,有兴趣的同学去研究,这里不详谈了,相比Stream.parallel()这种方式,我更倾向于后者。

4.总结

如果没有lambda,Stream用起来相当别扭,他会产生大量的匿名内部类,比如上面的3.1.2map例子,如果没有default method,集合框架更改势必会引起大量的改动,所以lambda+default method使得jdk库更加强大,以及灵活,Stream以及集合框架的改进便是最好的证明。

Das obige ist der detaillierte Inhalt vonInterpretieren Sie die neuen Funktionen von Java8 – die Rolle von Lambda. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage