English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Nuove caratteristiche di Java 8
L'API Java 8 aggiunge una nuova astrazione chiamata Stream, che ti permette di trattare i dati in modo dichiarativo.
Stream utilizza un modo intuitivo simile a SQL per interrogare i dati nel database per fornire un'alta astrazione delle operazioni e delle espressioni su Java Collection.
L'API Stream può aumentare notevolmente la produttività dei programmatori Java, permettendo loro di scrivere codice efficiente, pulito e semplice.
Questo stile considera l'insieme degli elementi da trattare come un flusso, che viene trasportato attraverso un tubo e può essere trattato nei nodi del tubo, ad esempio filtraggio, ordinamento, aggregazione, ecc.
Il flusso di elementi passa attraverso il trattamento delle operazioni intermedie (operazioni intermedie) e alla fine riceve i risultati del trattamento precedente dall'operazione finale (operazione finale).
+--------------------+ +------+ +------+ +---+ +-------+ | stream di elementi +-----> |filter+-> |sorted+-> |map+-> |collect| +--------------------+ +------+ +------+ +---+ +-------+
Il seguente flusso può essere convertito in codice Java come segue:
List<Integer> transactionsIds = widgets.stream() .filter(b -> b.getColor() == RED) .sorted((x,y) -> x.getWeight() - y.getWeight()) .mapToInt(Widget::getWeight) .sum();
Stream (flusso) è una coda di elementi provenienti da una fonte di dati e supporta operazioni di aggregazione
Coda degli elementi Gli elementi sono oggetti di tipo specifico, che formano una coda. Java non memorizza gli elementi tramite Stream, ma li calcola su richiesta.
Sorgente dei dati La fonte del flusso. Può essere una raccolta, un array, un canale I/O, un generatore generator, ecc.
Operazioni di aggregazione Operazioni simili a SQL, come filter, map, reduce, find, match, sorted, ecc.
Diversamente dalle operazioni Collection precedenti, le operazioni Stream hanno due caratteristiche fondamentali:
Pipelining: Le operazioni intermedie restituiscono sempre l'oggetto flusso stesso. In questo modo, più operazioni possono essere concatenate in una pipeline, come lo stile di flusso (fluent style). Questo permette di ottimizzare le operazioni, come l'esecuzione differita (laziness) e il cortocircuito (short-circuiting).
Iterazione interna: Prima la scansione della raccolta era fatta tramite Iterator o For-Each, esplicitamente fuori dalla raccolta, questo si chiama iterazione esterna. Stream fornisce un modo di iterazione interna, realizzato tramite il modello Visitor (Visitaore).
In Java 8, l'interfaccia della raccolta ha due metodi per generare flussi:
stream() − Crea un flusso sequenziale per la raccolta.
parallelStream() − Crea un flusso parallelo per la raccolta.
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
Stream fornisce un nuovo metodo 'forEach' per iterare ogni elemento del flusso di dati. Il seguente frammento di codice utilizza forEach per esportare 10 numeri casuali:
Random random = new Random(); random.ints().limit(10).forEach(System.out::println);
map 方法用于映射每个元素到对应的结果,以下代码片段使用 map 输出了元素对应的平方数:
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); // 获取对应的平方数 List<Integer> squaresList = numbers.stream().map(i -> i*i).distinct().collect(Collectors.toList());
filter 方法用于通过设置的条件过滤出元素。以下代码片段使用 filter 方法过滤出空字符串:
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl"); // 获取空字符串的数量 long count = strings.stream().filter(string -> string.isEmpty()).count();
limit 方法用于获取指定数量的流。以下代码片段使用 limit 方法打印出 10 条数据:
Random random = new Random(); random.ints().limit(10).forEach(System.out::println);
sorted 方法用于对流进行排序。以下代码片段使用 sorted 方法对输出的 10 个随机数进行排序:
Random random = new Random(); random.ints().limit(10).sorted().forEach(System.out::println);
parallelStream 是流并行处理程序的替代方法。以下示例我们使用 parallelStream 来输出空字符串的数量:
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); // 获取空字符串的数量 long count = strings.parallelStream().filter(string -> string.isEmpty()).count();
我们可以很容易地在顺序运行和并行直接切换。
Collectors 类实现了许多归约操作,例如将流转换为集合和聚合元素。Collectors 可用于返回列表或字符串:
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl"); List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList()); System.out.println("Elenco filtrato: " + filtered); String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", ")); System.out.println("Stringa combinata: " + mergedString);
Inoltre, alcuni collector che generano risultati statistici sono molto utili. Questi sono principalmente utilizzati per tipi di base come int, double, long, e possono essere utilizzati per generare risultati statistici simili a quelli seguenti.
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics(); System.out.println("Numero massimo nella lista: " + stats.getMax()); System.out.println("Numero minimo nella lista: " + stats.getMin()); System.out.println("Somma di tutti i numeri: " + stats.getSum()); System.out.println("Media: " + stats.getAverage());
Inserisci il seguente codice nel file Java8Tester.java:
import java.util.ArrayList; import java.util.Arrays; import java.util.IntSummaryStatistics; import java.util.List; import java.util.Random; import java.util.stream.Collectors; import java.util.Map; public class Java8Tester { public static void main(String args[]){ System.out.println("Utilizzando Java 7: "); // Calcolo delle stringhe vuote List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); System.out.println("Elenco: " + strings); long count = getCountEmptyStringUsingJava7(strings); System.out.println("Il numero di caratteri vuoti è: " + count); count = getCountLength2UsingJava7(strings); System.out.println("Numero di stringhe con lunghezza 3: " + count); // Elimina le stringhe vuote List<String> filtered = deleteEmptyStringsUsingJava7(strings); System.out.println("Lista filtrata: " + filtered); // Elimina le stringhe vuote e unisci con virgola String mergedString = getMergedStringUsingJava7(strings,", "); System.out.println("Stringa combinata: " + mergedString); List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); // Ottieni i quadrati degli elementi dell'elenco List<Integer> squaresList = getSquares(numbers); System.out.println("Elenco dei quadrati: " + squaresList); List<Integer> integers = Arrays.asList(1,2,13,4,15,6,17,8,19); System.out.println("Lista: " + integers); System.out.println("Numero massimo dell'elenco: " + getMax(integers)); System.out.println("Numero minimo dell'elenco: " + getMin(integers)); System.out.println("Somma di tutti i numeri: " + getSum(integers)); System.out.println("Media: " + getAverage(integers)); System.out.println("Numeri casuali: "); // Output di 10 numeri casuali Random random = new Random(); for(int i=0; i < 10; i++){ System.out.println(random.nextInt()); } System.out.println("Utilizzando Java 8: "); System.out.println("Elenco: " + strings); count = strings.stream().filter(string->string.isEmpty()).count(); System.out.println("Il numero di stringhe vuote è: " + count); count = strings.stream().filter(string -> string.length() == 3).count(); System.out.println("Numero di stringhe con lunghezza 3: " + count); filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList()); System.out.println("Lista filtrata: " + filtered); mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", ")); System.out.println("Stringa combinata: " + mergedString); squaresList = numbers.stream().map(i -> i * i).distinct().collect(Collectors.toList()); System.out.println("Elenco dei quadrati: " + squaresList); System.out.println("Lista: " + integers); IntSummaryStatistics stats = integers.stream().mapToInt((x) -> x).summaryStatistics(); System.out.println("Numero massimo nella lista: " + stats.getMax()); System.out.println("Numero minimo nella lista: " + stats.getMin()); System.out.println("Somma di tutti i numeri: " + stats.getSum()); System.out.println("Media: " + stats.getAverage()); System.out.println("Numeri casuali: "); random.ints().limit(10).sorted().forEach(System.out::println); // Elaborazione parallela count = strings.parallelStream().filter(string -> string.isEmpty()).count(); System.out.println("空字符串的数量为: " + count);} } private static int getCountEmptyStringUsingJava7(List<String> strings){ int count = 0; for(String string: strings){ if(string.isEmpty()){ count++; } } return count; } private static int getCountLength2UsingJava7(List<String> strings){ int count = 0; for(String string: strings){ if(string.length() == 3){ count++; } } return count; } private static List<String> deleteEmptyStringsUsingJava7(List<String> strings){ List<String> filteredList = new ArrayList<String>(); for(String string: strings){ if(!string.isEmpty()){ filteredList.add(string); } } return filteredList; } private static String getMergedStringUsingJava7(List<String> strings, String separator){ StringBuilder stringBuilder = new StringBuilder(); for(String string: strings){ if(!string.isEmpty()){ stringBuilder.append(string); stringBuilder.append(separator); } } String mergedString = stringBuilder.toString(); return mergedString.substring(0, mergedString.length()-2); } private static List<Integer> getSquares(List<Integer> numbers){ List<Integer> squaresList = new ArrayList<Integer>(); for(Integer number: numbers){ Integer square = new Integer(number.intValue() * number.intValue()); if(!squaresList.contains(square)){ squaresList.add(square); } } return squaresList; } private static int getMax(List<Integer> numbers){ int max = numbers.get(0); for(int i=1; i < numbers.size(); i++){ Integer number = numbers.get(i); if(number.intValue() > max){ max = number.intValue(); } } return max; } private static int getMin(List<Integer> numbers){ int min = numbers.get(0); for(int i=1; i < numbers.size(); i++){ Integer number = numbers.get(i); if(number.intValue() < min){ min = number.intValue(); } } return min; } private static int getSum(List numbers){ int sum = (int)(numbers.get(0)); for(int i=1; i < numbers.size(); i++){ sum += (int)numbers.get(i); } return sum; } private static int getAverage(List<Integer> numbers){ return getSum(numbers) / numbers.size(); } }
Eseguire lo script sopra, il risultato di output è:
$ javac Java8Tester.java $ java Java8Tester Usare Java 7: Elenco: [abc, , bc, efg, abcd, , jkl] Numero di caratteri vuoti: 2 Il numero di stringhe di lunghezza 3 è: 3 Elenco filtrato: [abc, bc, efg, abcd, jkl] Unione di stringhe: abc, bc, efg, abcd, jkl Elenco dei quadrati: [9, 4, 49, 25] Elenco: [1, 2, 13, 4, 15, 6, 17, 8, 19] Numero più grande nella lista: 19 Numero più piccolo nella lista: 1 Somma di tutti i numeri: 85 Media: 9 Numero casuale: -393170844 -963842252 447036679 -1043163142 -881079698 221586850 -1101570113 576190039 -1045184578 1647841045 Usando Java 8: Elenco: [abc, , bc, efg, abcd, , jkl] Il numero di stringhe vuote è: 2 Il numero di stringhe di lunghezza 3 è: 3 Elenco filtrato: [abc, bc, efg, abcd, jkl] Unione di stringhe: abc, bc, efg, abcd, jkl Elenco di quadrati: [9, 4, 49, 25] Elenco: [1, 2, 13, 4, 15, 6, 17, 8, 19] Numero più grande nella lista: 19 Numero più piccolo nella lista: 1 Somma di tutti i numeri: 85 Media: 9.444444444444445 Numero casuale: -1743813696 -1301974944 -1299484995 -779981186 136544902 555792023 1243315896 1264920849 1472077135 1706423674 Il numero di stringhe vuote è: 2