1. Use of stream basic method
1. filter filtering
The filter method is used to filter out elements that meet the conditions by setting conditions. The following code snippet uses the filter method to filter out empty strings.
List<String> list = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = list.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
2. sorted sorting
The sorted method is used to sort the stream. The following code snippet uses the sorted method to sort the numbers in the collection
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
numbers.stream().sorted().forEach(System.out::println);
Note:
Stream<T> sorted(); //
The sorted function of the natural sorting empty parameter calls the Comparable interface of the collection element by default for comparison. If it is a custom class, it needs to implement the Comparable interface and rewrite compareTo(Object obj)
Stream<T> sorted(Comparator<? super T> comparator); //
The sorted function with parameters for custom sorting needs to pass in the Comparator object, rewrite the compare(Object o1,object o2) method
3. map mapping
The map method is used to map each element to the corresponding result. The following code snippet uses a map to get a person's name
List<String> names = persons.stream().map(Person::getName).collect(Collectors.toList());
4. distinct deduplication
The distinct method is used to remove duplicate data. The following code snippet uses the filter method to filter out empty strings and remove duplicates
List<String> list = Arrays.asList("abc", "", "bc", "efg", "abc","", "jkl");
List<String> filtered = list.stream().filter(string -> !string.isEmpty()).distinct().collect(Collectors.toList());
5. Match matching
Stream provides a variety of matching operations that allow checking whether a specified Predicate matches the entire Stream. All matching operations are final and return a boolean value.
// 测试 Match (匹配)操作
List<String> stringList = Arrays.asList("abc", "", "bc", "efg", "abc","", "jkl");
// 部分匹配返回true
boolean anyStartsWithA =
stringList
.stream()
.anyMatch((s) -> s.startsWith("a"));
System.out.println(anyStartsWithA); // true
// 全部匹配返回true
boolean allStartsWithA =
stringList
.stream()
.allMatch((s) -> s.startsWith("a"));
System.out.println(allStartsWithA); // false
// 全部不匹配返回true
boolean noneStartsWithZ =
stringList
.stream()
.noneMatch((s) -> s.startsWith("z"));
System.out.println(noneStartsWithZ); // true
6. Reduce protocol
This is a final operation that allows multiple elements in the stream to be reduced to one element through the specified function, and the reduced result is expressed through the Optional interface:
//测试 Reduce (规约)操作
List<String> stringList = Arrays.asList("abc", "bc", "efg", "abc", "jkl");
Optional<String> reduced =
stringList
.stream()
.sorted()
.reduce((s1, s2) -> s1 + "#" + s2);
reduced.ifPresent(System.out::println);//abc#bc#efg#abc#jkl
// 字符串连接,concat = "ABCD"
String concat = Stream.of("A", "B", "C", "D").reduce("", String::concat);
// 求最小值,minValue = -3.0
double minValue = Stream.of(-1.5, 1.0, -3.0, -2.0).reduce(Double.MAX_VALUE, Double::min);
// 求和,sumValue = 10, 有起始值
int sumValue = Stream.of(1, 2, 3, 4).reduce(0, Integer::sum);
// 求和,sumValue = 10, 无起始值,返回Optional,通过get获取值
sumValue = Stream.of(1, 2, 3, 4).reduce(Integer::sum).get();
// 过滤,字符串连接,concat = "ace"
concat = Stream.of("a", "B", "c", "D", "e", "F").filter(x -> x.compareTo("Z") > 0).reduce("", String::concat);
The main function of this method is to combine Stream elements. It provides an initial value (seed), and then combines it with the first, second, and nth elements of the previous Stream according to the operation rules (BinaryOperator). In this sense, string concatenation, sum, min, max, and average of values are all special reduce. For example, the sum of Stream is equivalent to Integer sum = integers.reduce(0, (a, b) -> a+b); there is also a case where there is no starting value, then the first two elements of Stream will be combined and returned is Optional.
The first parameter (blank character) is the starting value, and the second parameter (String::concat) is the BinaryOperator. This type of reduce() with a starting value returns a concrete object. As for the reduce() in the fifth example, which has no starting value, it may return an Optional because there may not be enough elements. Please pay attention to this difference. For more content, see: IBM: Detailed Streams API in Java 8
7. count count
The count method is used to count the number of objects in the collection. The following code snippet uses the filter method to filter out empty strings and count them
List<String> list = Arrays.asList("abc", "", "bc", "efg", "abc","", "jkl");
long count = list.stream().filter(string -> !string.isEmpty()).count();
8.Collectors
The Collectors class implements many reduction operations, such as converting streams into collections and aggregating elements.
Collectors can be used to return lists or strings:
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("原列表筛选后列表: " + filtered);
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("合并字符串: " + mergedString);
2. List is grouped according to object attributes
底层代码:
1. public static <T, K> Collector<T, ?, Map<K, List<T>>>
groupingBy(Function<? super T, ? extends K> classifier) {
return groupingBy(classifier, toList());
}
2. public static <T, K, A, D>
Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier,
Collector<? super T, A, D> downstream) {
return groupingBy(classifier, HashMap::new, downstream);
}
3. public static <T, K, D, A, M extends Map<K, D>>
Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier,
Supplier<M> mapFactory,
Collector<? super T, A, D> downstream) {
Supplier<A> downstreamSupplier = downstream.supplier();
BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
BiConsumer<Map<K, A>, T> accumulator = (m, t) -> {
K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key");
A container = m.computeIfAbsent(key, k -> downstreamSupplier.get());
downstreamAccumulator.accept(container, t);
};
BinaryOperator<Map<K, A>> merger = Collectors.<K, A, Map<K, A>>mapMerger(downstream.combiner());
@SuppressWarnings("unchecked")
Supplier<Map<K, A>> mangledFactory = (Supplier<Map<K, A>>) mapFactory;
if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
return new CollectorImpl<>(mangledFactory, accumulator, merger, CH_ID);
}
else {
@SuppressWarnings("unchecked")
Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher();
Function<Map<K, A>, M> finisher = intermediate -> {
intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v));
@SuppressWarnings("unchecked")
M castResult = (M) intermediate;
return castResult;
};
return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_NOID);
}
}
1. Group by attribute field
Map<String, List<Person>> collect = list.stream().collect(Collectors.groupingBy(Person::getName));
2. Solve the problem that the Map is not in the order of the list
Map<String, List<Person>> collect = list.stream()
.collect(Collectors.groupingBy(Person::getName, LinkedHashMap::new,Collectors.toList()));
3. Sort in ascending order by field
The grouped fields are sorted according to the rules of TreeMap and put into Map, and the bottom layer is TreeMap
Map<String, List<Person>> collect = list.stream()
.collect(Collectors.groupingBy(Person::getAge, TreeMap::new, Collectors.toList())); //TreeMap默认以升序排序
4. Multiple grouping
Map<String, Map<String, List<PlanOrg>>> planOrgMap = new HashMap<>();
planOrgList.stream().collect(Collectors.groupingBy(PlanOrg::getType)).
forEach((type, list2) -> {
Map<String, List<PlanOrg>> planOrgMap_tmp = list2.stream().collect(
Collectors.groupingBy(PlanOrg::getPlanOrgId)
);
planOrgMap.put(type, planOrgMap_tmp);
});
3. List collection statistical operations: summation, maximum value, minimum value, and average value
1. Statistics
long count = Persons.stream().filter(a -> a.getAge() > 5).count();
System.out.println("age > 5的人数 = " + count);
2. Sum
int sumAge = persons.stream().mapToInt(Person::getAge).sum();
3. Find the maximum value
int maxAge = persons.stream().mapToInt(Person::getAge).max().getAsInt();
4. Find the minimum value
int minAge = persons.stream().mapToInt(Person::getAge).min().getAsInt();
5. Average
double avgAge = persons.stream().mapToInt(Person::getAge).average().getAsDouble();
6.summaryStatistics statistics
A stream cannot be used for the second time after being used once, and all statistics information of a stream can be obtained at one time.
IntSummaryStatistics statistics = persons.stream().mapToInt(Person::getAge).summaryStatistics();
System.out.println("count = " + statistics.getCount());
System.out.println("sumAge = " + statistics.getSum());
System.out.println("maxAge = " + statistics.getMax());
System.out.println("minAge = " + statistics.getMin());
System.out.println("avgAge = " + statistics.getAverage());