企业网站优化工具,做空间的网站吗,做药品的电商网站有哪些,徐州网站制作功能一、概述
在使用stream之前#xff0c;先理解Optional 。
Optional是Java 8引入的一个容器类#xff0c;用于处理可能为空的值。它提供了一种优雅的方式来处理可能存在或不存在的值#xff0c;避免了空指针异常。
Optional的主要特点如下#xff1a;
可能为空#xff…一、概述
在使用stream之前先理解Optional 。
Optional是Java 8引入的一个容器类用于处理可能为空的值。它提供了一种优雅的方式来处理可能存在或不存在的值避免了空指针异常。
Optional的主要特点如下
可能为空Optional可以包含一个非空的值也可以表示为空。避免空指针异常通过使用Optional可以避免在访问可能为空的值时出现空指针异常。显式判断使用Optional需要显式地判断值是否存在以便进行相应的处理。函数式操作Optional提供了一系列的函数式操作方法如map()、filter()、orElse()等方便对Optional中的值进行转换、过滤和默认值处理。 使用Stream可以对集合或数组中的元素进行各种转换、过滤和映射等操作以实现更简洁、灵活和函数式的编程风格。下面是使用Stream的一般步骤
创建Stream通过集合、数组、IO通道或Stream的静态方法来创建一个Stream对象。中间操作Intermediate Operations使用中间操作方法对Stream进行转换、过滤、映射等操作返回一个新的Stream对象。常见的中间操作包括filter()、map()、sorted()、distinct()等。终止操作Terminal Operations使用终止操作方法对Stream进行最终的计算或收集操作返回一个结果或一个最终的集合。常见的终止操作包括forEach()、collect()、reduce()、min()、max()等。 二、Stream的创建
在Java中可以使用多种方式来创建Stream对象。下面是一些常见的创建Stream的方法 1. 通过集合创建Stream
通过集合创建Stream是一种常见的方式Java8 中的 Collection 接口被扩展提供两个获取流的方法 :
Stream stream() : 返回一个顺序流Stream parallelStream() : 返回一个并行流
StreamInteger stream1 Arrays.asList(1,2,3,4).stream();
StreamInteger stream2 Arrays.asList(1,2,3,4).parallelStream(); 2. 通过数组创建Stream
通过数组创建Stream可以使用Arrays.stream()方法来实现。该方法接受一个数组作为参数并返回一个对应类型的Stream对象。
int[] array {1, 2, 3, 4, 5};
IntStream stream Arrays.stream(array); 3. 通过Stream的静态方法创建Stream
通过Stream的静态方法可以使用of()、iterate()和generate()等方法来创建Stream对象。使用IntStream、LongStream、DoubleStream的static方法创建有限流可以使用of()、range()和rangeClosed()等方法来创建Stream对象。使用随机数类的ints()方法创建无限数值流
// 使用of()方法创建Stream
StreamString stream1 Stream.of(apple, banana, orange);
// 使用iterate()方法创建Stream
StreamInteger stream2 Stream.iterate(0, n - n 2).limit(10);
// 使用generate()方法创建Stream
StreamDouble stream3 Stream.generate(Math::random).limit(5);// 使用of()方法创建IntStream
IntStream.of(new int[]{1, 2, 3});
// 使用range()方法创建IntStream
IntStream.range(1, 3);
// 使用rangeClosed()方法创建IntStream
IntStream.rangeClosed(1, 3);// 使用随机数类的ints()方法创建无限数值流
Random random new Random();
IntStream ints random.ints(); 4. 通过IO通道创建Stream
使用BufferedReader的lines方法从文件中获得行的流Files类的操作路径的方法如list、find、walk、lines等
// 使用BufferedReader的lines方法从文件中获得行的流
BufferedReader bufferedReader new BufferedReader(new InputStreamReader(new FileInputStream(file.txt)));
StreamString lines bufferedReader.lines();Path path Paths.get(file.txt);
StreamString lines Files.lines(path); 5. 通过其他类提供的创建Stream
BitSet数值流Pattern 将字符串分隔成流JarFile 读取jar文件流
// BitSet数值流
IntStream stream new BitSet().stream();// Pattern 将字符串分隔成流
Pattern pattern compile(,);
StreamString stringStream pattern.splitAsStream(a,b,c,d);
stringStream.forEach(System.out::println);// JarFile 读取jar文件流
StreamJarEntry stream new JarFile().stream(); 这些方法提供了不同的方式来创建Stream对象可以根据具体的需求选择适当的创建方式。创建Stream后可以使用Stream的中间操作和终止操作来对数据进行处理和操作。
需要注意的是Stream对象是一次性使用的一旦对Stream进行了终止操作就不能再对同一个Stream进行其他操作。如果需要对同一组数据进行多个操作可以创建多个Stream对象来实现。 三、中间操作
3.1 筛选filter
筛选是按照一定的规则校验流中的元素将符合条件的元素提取到新的流中的操作。
filter()是Java Stream API中的一个中间操作方法用于根据指定的条件过滤流中的元素。它接受一个Predicate函数式接口作为参数该接口定义了一个用于判断元素是否满足条件的方法。
filter()方法的语法StreamT filter(Predicate? super T predicate)
其中T表示流中的元素类型predicate表示用于判断元素是否满足条件的Predicate对象。 filter()方法的工作原理如下
对于流中的每个元素filter()方法会调用传入的Predicate对象的test()方法将当前元素作为参数传递给test()方法。如果test()方法返回true则表示当前元素满足条件会被保留在新的流中。如果test()方法返回false则表示当前元素不满足条件会被过滤掉不包含在新的流中。
下面是一个示例代码演示了如何使用filter()方法过滤出偶数
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class StreamFilterExample {public static void main(String[] args) {ListInteger numbers Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);// 使用filter()方法过滤出偶数ListInteger evenNumbers numbers.stream().filter(n - n % 2 0).collect(Collectors.toList());// 输出结果System.out.println(evenNumbers); // [2, 4, 6, 8, 10]}
}
在上面的示例中我们首先创建了一个包含整数的列表。然后我们使用filter()方法过滤出偶数通过传入的Lambda表达式判断元素是否为偶数。最后我们使用collect()方法将过滤后的结果收集到一个新的列表中并输出结果。
通过使用filter()方法我们可以根据指定的条件过滤流中的元素只保留满足条件的元素实现对数据的筛选和过滤操作。 3.2 元素转换(peek/map/flatMap)
在Java的Stream API中peek()、map()和flatMap()是常用的中间操作方法用于对流中的元素进行转换、处理和操作。
peek()方法
peek()方法接受一个Consumer函数式接口作为参数对流中的每个元素执行指定的操作并返回一个新的流。peek()方法可以用于调试和观察流中的元素但不会改变流中元素的内容。peek()方法是一个中间操作它返回的是与原始流相同类型的新流。 map()方法
map()方法接受一个Function函数式接口作为参数将流中的每个元素映射为另一个元素并返回一个新的流。map()方法可以用于对流中的元素进行转换、提取或计算等操作。map()方法是一个中间操作它返回的是与原始流中元素类型不同的新流。 flatMap()方法
flatMap()方法接受一个Function函数式接口作为参数将流中的每个元素映射为一个流并将所有流连接成一个新的流。flatMap()方法可以用于扁平化嵌套的流结构将多个流合并为一个流。flatMap()方法是一个中间操作它返回的是与原始流中元素类型不同的新流。
下面是一个示例代码演示了peek()、map()和flatMap()的使用
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class StreamOperationsExample {public static void main(String[] args) {ListString words Arrays.asList(Hello, World, Java);// 使用peek()方法调试和观察流中的元素ListString peekResult words.stream().peek(System.out::println).collect(Collectors.toList());// 使用map()方法将每个单词转换为大写ListString mapResult words.stream().map(String::toUpperCase).collect(Collectors.toList());// 使用flatMap()方法将每个单词拆分为字母ListString flatMapResult words.stream().flatMap(word - Arrays.stream(word.split())).collect(Collectors.toList());// 输出结果System.out.println(Peek Result: peekResult);System.out.println(Map Result: mapResult);System.out.println(FlatMap Result: flatMapResult);}
}
在上面的示例中我们首先创建了一个包含单词的列表。然后我们使用peek()方法对流中的元素进行调试和观察并使用map()方法将每个单词转换为大写最后使用flatMap()方法将每个单词拆分为字母。最终我们使用collect()方法将结果收集到一个新的列表中并输出结果。
通过使用peek()、map()和flatMap()等方法我们可以对流中的元素进行转换、处理和操作实现更加灵活和函数式的编程风格。 3.3 排序(sorted)
sorted()是Java Stream API中的一个中间操作方法用于对流中的元素进行排序。它可以按照自然顺序或者通过自定义的Comparator来进行排序。
sorted()方法的语法StreamT sorted() / StreamT sorted(Comparator? super T comparator)
其中T表示流中的元素类型comparator表示用于比较元素的Comparator对象。 sorted()方法的工作原理如下
对于无参的sorted()方法它会使用元素的自然顺序进行排序。元素类型必须实现Comparable接口否则会抛出ClassCastException。对于带有Comparator参数的sorted()方法它会使用指定的Comparator对象来进行排序。Comparator定义了元素之间的比较规则。
下面是一个示例代码演示了如何使用sorted()方法对整数列表进行排序
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class StreamSortedExample {public static void main(String[] args) {ListInteger numbers Arrays.asList(5, 2, 8, 1, 9, 3);// 使用sorted()方法对整数列表进行排序ListInteger sortedNumbers numbers.stream().sorted().collect(Collectors.toList());// 输出结果System.out.println(sortedNumbers); // [1, 2, 3, 5, 8, 9]}
}
在上面的示例中我们首先创建了一个包含整数的列表。然后我们使用sorted()方法对整数列表进行排序默认按照自然顺序进行排序。最后我们使用collect()方法将排序后的结果收集到一个新的列表中并输出结果。
通过使用sorted()方法我们可以对流中的元素进行排序使得元素按照指定的顺序排列。可以根据需要使用自然顺序或自定义的Comparator来进行排序操作。 3.4 截取/跳过(limit/skip)
limit()和skip()是Java Stream API中的两个中间操作方法用于限制流中元素的数量。 limit()方法
limit()方法接受一个long类型的参数用于限制流中元素的数量。它返回一个新的流其中包含原始流中的前n个元素如果原始流中的元素不足n个则返回所有元素。 skip()方法
skip()方法接受一个long类型的参数用于跳过流中的前n个元素。它返回一个新的流其中包含原始流中剩余的元素如果原始流中的元素少于n个则返回空流。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class StreamLimitSkipExample {public static void main(String[] args) {ListInteger numbers Arrays.asList(1, 2, 3, 4, 5);// 使用limit()方法限制流中元素的数量ListInteger limitedNumbers numbers.stream().limit(3).collect(Collectors.toList());// 使用skip()方法跳过流中的前N个元素ListInteger skippedNumbers numbers.stream().skip(2).collect(Collectors.toList());// 输出结果System.out.println(limitedNumbers); // [1, 2, 3]System.out.println(skippedNumbers); // [3, 4, 5]}
}
在上面的示例中我们首先创建了一个包含整数的列表。然后我们使用limit()方法限制流中元素的数量为3个通过collect()方法将结果收集到一个新的列表中。接着我们使用skip()方法跳过流中的前2个元素同样通过collect()方法将结果收集到另一个新的列表中。最后我们输出限制和跳过操作后的结果。 通过使用limit()和skip()方法我们可以对流中的元素进行数量的限制和跳过操作实现对数据的筛选和截取。 3.5 合并(concat)
concat()是Java Stream API中的一个静态方法用于将两个流连接起来形成一个新的流。它接受两个相同类型的流作为参数并返回一个包含两个流中所有元素的新流。
concat()方法的语法static T StreamT concat(Stream? extends T a, Stream? extends T b)
其中T表示流中的元素类型a和b表示要连接的两个流。 concat()方法的工作原理如下
它会将第一个流的所有元素放在新流中然后将第二个流的所有元素追加到新流的末尾。新流中的元素顺序与原始流的顺序保持一致。
下面是一个示例代码演示了如何使用concat()方法连接两个流
import java.util.stream.Stream;public class StreamConcatExample {public static void main(String[] args) {StreamInteger stream1 Stream.of(1, 2, 3);StreamInteger stream2 Stream.of(4, 5, 6);// 使用concat()方法连接两个流StreamInteger concatenatedStream Stream.concat(stream1, stream2);// 输出结果concatenatedStream.forEach(System.out::println); // 1, 2, 3, 4, 5, 6}
}
在上面的示例中我们首先创建了两个整数流。然后我们使用concat()方法将这两个流连接起来形成一个新的流。最后我们使用forEach()方法遍历并打印连接后的结果。
通过使用concat()方法我们可以将两个流连接起来形成一个包含两个流中所有元素的新流。这对于需要合并多个流的场景非常有用。 3.6 去重(distinct)
distinct()是Java Stream API中的一个中间操作方法用于去除流中的重复元素。它会返回一个新的流其中包含原始流中的所有不重复的元素。
distinct()方法使用元素的equals()方法来判断元素是否重复。如果两个元素相等则只保留第一个出现的元素后续出现的相同元素将被过滤掉。
distinct()方法的语法StreamT distinct()
其中T表示流中的元素类型。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class StreamDistinctExample {public static void main(String[] args) {ListInteger numbers Arrays.asList(1, 2, 3, 2, 4, 3, 5);// 使用distinct()方法去除重复元素ListInteger distinctNumbers numbers.stream().distinct().collect(Collectors.toList());// 输出结果System.out.println(distinctNumbers); // [1, 2, 3, 4, 5]}
}
在上面的示例中我们首先创建了一个包含整数的列表。然后我们使用distinct()方法去除列表中的重复元素并通过collect()方法将结果收集到一个新的列表中。最后我们输出去除重复元素后的结果。
通过使用distinct()方法我们可以方便地去除流中的重复元素得到一个只包含不重复元素的新流。这对于数据去重和筛选操作非常有用。 四、终止操作
4.1 遍历/匹配foreach/findAny/findFirst/anyMatch/allMatch/noneMatch
在Java Stream API中forEach()、findAny()、findFirst()和anyMatch()、allMatch()、noneMatch()是常用的终止操作方法用于对流中的元素进行遍历、查找和匹配。 forEach()方法
forEach()方法接受一个Consumer函数式接口作为参数对流中的每个元素执行指定的操作。它没有返回值只是对流中的每个元素进行操作。 findAny()和findFirst()方法
findAny()方法返回流中的任意一个元素如果流为空则返回Optional.empty()。findFirst()方法返回流中的第一个元素如果流为空则返回Optional.empty()。 anyMatch()、allMatch()和noneMatch()方法
anyMatch()方法接受一个Predicate函数式接口作为参数判断流中是否存在满足指定条件的元素。allMatch()方法接受一个Predicate函数式接口作为参数判断流中的所有元素是否都满足指定条件。noneMatch()方法接受一个Predicate函数式接口作为参数判断流中是否没有任何元素满足指定条件。这些方法返回一个boolean类型的结果表示是否存在满足条件的元素。
import java.util.Arrays;
import java.util.List;public class StreamTerminalOperationsExample {public static void main(String[] args) {ListInteger numbers Arrays.asList(1, 2, 3, 4, 5);// 使用forEach()方法遍历每个元素numbers.stream().forEach(System.out::println);// 使用findAny()方法找到任意一个元素Integer anyNumber numbers.stream().findAny().orElse(null);// 使用findFirst()方法找到第一个元素Integer firstNumber numbers.stream().findFirst().orElse(null);// 使用anyMatch()方法判断是否存在大于3的元素boolean anyGreaterThanThree numbers.stream().anyMatch(n - n 3);// 使用allMatch()方法判断是否所有元素都小于10boolean allLessThanTen numbers.stream().allMatch(n - n 10);// 使用noneMatch()方法判断是否没有任何元素等于6boolean noneEqualsSix numbers.stream().noneMatch(n - n 6);// 输出结果System.out.println(Any Number: anyNumber);System.out.println(First Number: firstNumber);System.out.println(Any Greater Than Three: anyGreaterThanThree);System.out.println(All Less Than Ten: allLessThanTen);System.out.println(None Equals Six: noneEqualsSix);}
}
在上面的示例中我们首先创建了一个包含整数的列表。然后我们使用不同的终止操作方法对流中的元素进行遍历、查找和匹配操作并输出结果。
通过使用这些终止操作方法我们可以对流中的元素进行遍历、查找和匹配操作得到相应的结果。 4.2 聚合max/min/count)
在Java Stream API中max()、min()和count()是常用的终止操作方法用于获取流中的最大值、最小值和元素数量。 max()方法
max()方法接受一个Comparator函数式接口作为参数用于比较流中的元素。它返回流中的最大元素如果流为空则返回Optional.empty()。 min()方法
min()方法接受一个Comparator函数式接口作为参数用于比较流中的元素。它返回流中的最小元素如果流为空则返回Optional.empty()。 count()方法
count()方法返回流中的元素数量返回一个long类型的结果。
import java.util.Arrays;
import java.util.List;
import java.util.Optional;public class StreamTerminalOperationsExample {public static void main(String[] args) {ListInteger numbers Arrays.asList(1, 2, 3, 4, 5);// 使用max()方法找到最大值OptionalInteger maxNumber numbers.stream().max(Integer::compare);// 使用min()方法找到最小值OptionalInteger minNumber numbers.stream().min(Integer::compare);// 使用count()方法计算元素数量long count numbers.stream().count();// 输出结果System.out.println(Max Number: maxNumber.orElse(null));System.out.println(Min Number: minNumber.orElse(null));System.out.println(Count: count);}
}
在上面的示例中我们首先创建了一个包含整数的列表。然后我们使用不同的终止操作方法对流中的元素进行最大值、最小值和计数操作并输出结果。
通过使用这些终止操作方法我们可以方便地获取流中的最大值、最小值和元素数量。需要注意的是max()和min()方法返回的是Optional类型的结果因为流中可能为空。 4.3 归约(reduce)
reduce()是Java Stream API中的一个终止操作方法用于将流中的元素按照指定的规约操作进行合并返回一个最终的结果。归约也称缩减顾名思义是把一个流缩减成一个值能实现对集合求和、求乘积和求最值操作。
reduce()方法接受一个BinaryOperator函数式接口作为参数该接口定义了一个二元操作用于将两个元素进行合并。它还可以接受一个初始值作为累加器的初始值。
reduce()方法的语法
OptionalT reduce(BinaryOperatorT accumulator)
T reduce(T identity, BinaryOperatorT accumulator)
其中T表示流中的元素类型accumulator表示用于合并元素的操作identity表示累加器的初始值。 reduce()方法的工作原理如下
对于流中的第一个元素将其作为累加器的初始值。对于后续的每个元素使用累加器和当前元素进行合并操作得到一个新的累加器值。最终返回合并后的累加器值。
import java.util.Arrays;
import java.util.List;
import java.util.Optional;public class StreamReduceExample {public static void main(String[] args) {ListInteger numbers Arrays.asList(1, 2, 3, 4, 5);// 使用reduce()方法对整数列表进行求和OptionalInteger sum numbers.stream().reduce(Integer::sum);// 输出结果System.out.println(Sum: sum.orElse(0));}
}
在上面的示例中我们首先创建了一个包含整数的列表。然后我们使用reduce()方法对整数列表进行求和通过传入的Integer::sum方法作为累加器进行合并操作。最后我们使用orElse()方法获取求和结果并输出结果。
通过使用reduce()方法我们可以对流中的元素进行合并操作实现对数据的聚合和规约。需要注意的是reduce()方法返回的是Optional类型的结果因为流中可能为空。 4.4 收集(collect)
collect收集就是把一个流收集起来最终可以是收集成一个值也可以收集成一个新的集合。
collect()用于将流中的元素收集到一个集合或其他数据结构中。
collect()方法接受一个Collector对象作为参数该对象定义了如何将流中的元素进行收集和组合。Collector接口提供了一系列静态方法来创建常见的收集器实例。
下面是collect()方法的语法R R collect(Collector? super T, A, R collector)
其中T表示流中的元素类型A表示中间结果的类型R表示最终结果的类型。 collect()方法的工作原理如下
它会使用Collector对象中定义的逻辑对流中的元素进行收集和组合。最终返回一个包含收集结果的对象可以是List、Set、Map等。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class StreamCollectExample {public static void main(String[] args) {ListInteger numbers Arrays.asList(1, 2, 3, 4, 5);// 使用collect()方法将偶数收集到一个新的列表中ListInteger evenNumbers numbers.stream().filter(n - n % 2 0).collect(Collectors.toList());// 输出结果System.out.println(evenNumbers); // [2, 4]}
}
在上面的示例中我们首先创建了一个包含整数的列表。然后我们使用filter()方法过滤出偶数并通过collect()方法将结果收集到一个新的列表中。最后我们输出收集后的结果。
通过使用collect()方法我们可以方便地将流中的元素收集到一个集合或其他数据结构中实现对数据的聚合和收集操作。 4.4.1 归集(toList/toSet/toMap)
因为流不存储数据那么在流中的数据完成处理后需要将流中的数据重新归集到新的集合里。toList、toSet和toMap比较常用另外还有toCollection、toConcurrentMap等复杂一些的用法。
在Java Stream API中有多个方法可用于将流中的元素收集到不同类型的集合或映射中。
toList()方法 toList()方法将流中的元素收集到一个列表中。它返回一个包含流中所有元素的新列表。
toSet()方法 toSet()方法将流中的元素收集到一个集合中。它返回一个包含流中所有元素的新集合。
toMap()方法 toMap()方法将流中的元素收集到一个映射中。它接受两个Function函数式接口作为参数用于提取键和值并返回一个包含流中所有键值对的新映射。
toCollection()方法 toCollection()方法将流中的元素收集到指定类型的集合中。它接受一个Supplier函数式接口作为参数用于提供一个自定义的集合实例。
toConcurrentMap()方法 toConcurrentMap()方法将流中的元素收集到一个并发映射中。它接受三个Function函数式接口作为参数用于提取键、值和处理键冲突的方式。
这些方法都是终止操作它们根据需要将流中的元素收集到不同类型的集合或映射中。根据具体的需求和数据结构可以选择适当的方法来进行元素的收集和聚合操作。
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;public class StreamCollectExample {public static void main(String[] args) {ListInteger numbers Arrays.asList(1, 2, 3, 4, 5);// 使用toList()方法将元素收集到列表中ListInteger list numbers.stream().collect(Collectors.toList());// 使用toSet()方法将元素收集到集合中SetInteger set numbers.stream().collect(Collectors.toSet());// 使用toMap()方法将元素收集到映射中MapInteger, String map numbers.stream().collect(Collectors.toMap(num - num,num - Value num));// 使用toCollection()方法将元素收集到自定义集合中SetInteger customSet numbers.stream().collect(Collectors.toCollection(() - new CustomSet()));// 使用toConcurrentMap()方法将元素收集到并发映射中MapInteger, String concurrentMap numbers.stream().collect(Collectors.toConcurrentMap(num - num,num - Value num,(v1, v2) - v1 , v2,ConcurrentHashMap::new));// 输出结果System.out.println(List: list); // [1, 2, 3, 4, 5]System.out.println(Set: set); // [1, 2, 3, 4, 5]System.out.println(Map: map); // {1Value1, 2Value2, 3Value3, 4Value4, 5Value5}System.out.println(Custom Set: customSet);System.out.println(Concurrent Map: concurrentMap);}
}class CustomSetT extends HashSetT {// 自定义集合类
}
通过使用toList()、toSet()和toMap()等方法我们可以方便地将流中的元素收集到列表、集合或映射中实现对数据的聚合和收集操作。
通过使用toCollection()和toConcurrentMap()等方法我们可以方便地将流中的元素收集到自定义的集合或并发映射中实现对数据的聚合和收集操作。 4.4.2 统计(count/averaging/max(min)/summing/summarizing)
在Java Stream API中有多个终止操作方法可以用于对流中的元素进行计数、平均值、最大值、最小值、求和和统计等操作。
count()方法 count()方法返回流中的元素数量。它返回一个long类型的结果表示流中的元素数量。
averagingXxx()方法 averagingXxx()方法用于计算流中元素的平均值其中Xxx可以是Int、Long或Double。它返回一个double类型的结果表示流中元素的平均值。
maxBy()和minBy()方法 maxBy()方法接受一个Comparator函数式接口作为参数返回流中的最大元素。minBy()方法接受一个Comparator函数式接口作为参数返回流中的最小元素。它们返回一个Optional对象表示流中的最大或最小元素。
summingXxx()方法 summingXxx()方法用于对流中的元素进行求和其中Xxx可以是Int、Long或Double。它返回一个Xxx类型的结果表示流中元素的总和。
summarizingXxx()方法 summarizingXxx()方法用于对流中的元素进行统计其中Xxx可以是Int、Long或Double。它返回一个包含元素数量、总和、平均值、最大值和最小值的XxxSummaryStatistics对象。
import java.util.Arrays;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;public class StreamStatisticsExample {public static void main(String[] args) {ListInteger numbers Arrays.asList(1, 2, 3, 4, 5);// 使用count()方法统计元素数量long count numbers.stream().count();// 使用averagingXxx()方法计算平均值double average numbers.stream().collect(Collectors.averagingInt(Integer::intValue));// 使用maxBy()方法找到最大值OptionalInteger max numbers.stream().max(Integer::compare);// 使用minBy()方法找到最小值OptionalInteger min numbers.stream().min(Integer::compare);// 使用summingXxx()方法求和int sum numbers.stream().collect(Collectors.summingInt(Integer::intValue));// 使用summarizingXxx()方法进行统计IntSummaryStatistics statistics numbers.stream().collect(Collectors.summarizingInt(Integer::intValue));// 输出结果System.out.println(Count: count);System.out.println(Average: average);System.out.println(Max: max.orElse(null));System.out.println(Min: min.orElse(null));System.out.println(Sum: sum);System.out.println(Statistics: statistics);}
}
在上面的示例中我们首先创建了一个包含整数的列表。然后我们使用不同的终止操作方法对流中的元素进行计数、平均值、最大值、最小值、求和和统计操作并输出结果。
通过使用这些终止操作方法我们可以方便地对流中的元素进行各种统计操作得到相应的结果。 4.4.3 分组(partitioningBy/groupingBy)
在Java Stream API中partitioningBy()和groupingBy()是用于对流中的元素进行分区和分组的收集器。
partitioningBy()方法
partitioningBy()方法接受一个Predicate函数式接口作为参数用于将流中的元素分为满足条件和不满足条件的两个部分。它返回一个MapBoolean, ListT类型的结果其中Boolean表示分区的键ListT表示满足或不满足条件的元素列表。
groupingBy()方法
groupingBy()方法接受一个Function函数式接口作为参数用于根据指定的分类函数对流中的元素进行分组。它返回一个MapK, ListT类型的结果其中K表示分组的键ListT表示具有相同键的元素列表。
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;public class StreamPartitioningGroupingExample {public static void main(String[] args) {ListInteger numbers Arrays.asList(1, 2, 3, 4, 5, 6);// 使用partitioningBy()方法将奇偶数分区MapBoolean, ListInteger partitionedNumbers numbers.stream().collect(Collectors.partitioningBy(n - n % 2 0));// 使用groupingBy()方法将数字按照奇偶分组MapString, ListInteger groupedNumbers numbers.stream().collect(Collectors.groupingBy(n - n % 2 0 ? Even : Odd));// 输出结果System.out.println(Partitioned Numbers: partitionedNumbers);System.out.println(Grouped Numbers: groupedNumbers);}
}
在上面的示例中我们首先创建了一个包含整数的列表。然后我们使用partitioningBy()方法将列表中的元素按照奇偶数进行分区使用groupingBy()方法将列表中的元素按照奇偶进行分组。最后我们输出分区和分组的结果。
通过使用partitioningBy()和groupingBy()方法我们可以方便地对流中的元素进行分区和分组操作实现对数据的分类和归类。 4.4.4 接合(joining)
在Java Stream API中joining()是一个终止操作方法用于将流中的元素连接成一个字符串。
joining()方法没有参数它返回一个包含流中所有元素连接后的字符串。默认情况下元素之间使用空字符串作为分隔符进行连接但也可以通过提供自定义的分隔符来指定连接时使用的分隔符。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class StreamJoiningExample {public static void main(String[] args) {ListString words Arrays.asList(Hello, World, Java);// 使用joining()方法将字符串列表中的元素连接成一个字符串String result words.stream().collect(Collectors.joining());// 输出结果System.out.println(result); // HelloWorldJava// 使用自定义分隔符连接字符串列表中的元素String customResult words.stream().collect(Collectors.joining(, ));// 输出结果System.out.println(customResult); // Hello, World, Java}
}
在上面的示例中我们首先创建了一个包含字符串的列表。然后我们使用joining()方法将列表中的元素连接成一个字符串默认使用空字符串作为分隔符。接着我们使用自定义的分隔符 , 来连接字符串列表中的元素。最后我们输出连接后的结果。
通过使用joining()方法我们可以方便地将流中的元素连接成一个字符串实现对数据的合并和拼接操作。 4.4.5 归约(reducing)
在Java Stream API中reducing()是一个终止操作方法用于将流中的元素按照指定的规约操作进行合并返回一个最终的结果。
reducing()方法接受一个初始值和一个BinaryOperator函数式接口作为参数该接口定义了一个二元操作用于将两个元素进行合并。它还可以接受一个Function函数式接口用于将流中的元素转换为另一种类型。
下面是reducing()方法的语法
OptionalT reducing(BinaryOperatorT accumulator)
T reducing(T identity, BinaryOperatorT accumulator)
U U reducing(U identity, Function? super T, ? extends U mapper, BinaryOperatorU accumulator)
其中T表示流中的元素类型U表示结果的类型accumulator表示用于合并元素的操作identity表示初始值mapper表示元素转换的函数。 reducing()方法的工作原理如下
对于流中的第一个元素将其作为累加器的初始值。对于后续的每个元素使用累加器和当前元素进行合并操作得到一个新的累加器值。最终返回合并后的累加器值。
import java.util.Arrays;
import java.util.List;
import java.util.Optional;public class StreamReducingExample {public static void main(String[] args) {ListInteger numbers Arrays.asList(1, 2, 3, 4, 5);// 使用reducing()方法对整数列表进行求和OptionalInteger sum numbers.stream().reduce(Integer::sum);// 输出结果System.out.println(Sum: sum.orElse(0));}
}
在上面的示例中我们首先创建了一个包含整数的列表。然后我们使用reduce()方法对整数列表进行求和通过传入的Integer::sum方法作为累加器进行合并操作。最后我们使用orElse()方法获取求和结果并输出结果。
通过使用reducing()方法我们可以对流中的元素进行合并操作实现对数据的聚合和规约。需要注意的是reduce()方法返回的是Optional类型的结果因为流中可能为空。