文章目录
- 前言
- 一、filter
- 二、map
- 三、mapToInt、mapToLong、mapToDouble
- 四、flatMap
- 五、flatMapToInt、flatMapToLong、flatMapToDouble
- 六、distinct
- 七、sorted
- 八、peek
- 九、limit
- 十、forEach
- 十一、forEachOrdered
- 十二、toArray
- 十三、reduce
- 十四、collect
- 十五、min、max
- 十六、count
- 十七、anyMatch、allMatch、noneMatch
- 十八、findFirst、findAny
- 十九、builder
- 二十、of
- 二十一、iterate
- 二十二、generate
- 二十三、concat
- 总结
前言
想象一下,当你在编写一段复杂的代码时,突然有一种魔法💫可以让你的代码变得简洁又易读。
是不是很像科幻小说的情节?😄🎉
但是,Java 8的Stream流却能帮你实现这个梦想!✨
它就像一位技术大师,悄悄地走进了Java的大门,带来了编程世界的一次革命!💫✨
Stream流让我们能够以一种流畅的方式处理集合数据,解决了代码中循环和条件语句的臃肿问题。
想象一下,你不再需要写一堆循环来遍历数据,而是可以使用简洁的链式调用来完成各种操作。
不禁让人感叹,这简直就是程序员们的福音啊!🚀🌟
Stream流的魔力可不止于此!!!
它还可以让我们对数据进行筛选、排序、映射、归约等操作,就像在玩一场代码的魔法方块🧩,把数据进行各种变换和组合。
不仅如此,它还能让我们轻松处理大数据量,提高我们的开发效率。🚀🚀🚀
你可能会觉得,听起来好像有点夸张吧?💫
不过,我保证你一旦掌握了Stream流的技巧,就会爱不释手!就像拥有了一把魔法棒🧩,能够在代码的世界中释放出无穷的创造力。🎉
所以,亲爱的朋友们,如果你们还在为冗长的代码而苦恼,还在为难以理解的循环而犯愁,那就赶快加入我们的Stream流冒险队伍吧!🎉
通过本篇博客的指导,你将轻松掌握Stream流的诀窍,从而开启一段幽默有趣的编程之旅。😁🌈
准备好了吗?🌈🌈🌈
让我们一起笑着、学着、玩着,探索Stream流的代码简洁之道吧!
记住,Java 8 Stream流不仅仅是一段代码,更是一场奇幻冒险,让我们享受这一段令人愉快的编程之旅吧!🚀🚀🚀
一、filter
当涉及到数据处理和筛选时,filter() 方法是一个非常常用的方法。它可以用于过滤集合、数组或流中的元素,根据指定的条件只保留满足条件的元素,从而生成一个新的集合或流。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
List<Integer> evenNumbers = numbers.stream().filter(num -> num % 2 == 0).collect(Collectors.toList());
上述代码通过将集合转换为 Stream,然后在 Stream 上调用 filter() 方法,并提供一个谓词(Predicate)来指定过滤条件。最后使用 collect() 方法将满足条件的元素收集到一个新的集合中。
二、map
map() 方法是一个集合操作方法,用于对集合中的每个元素应用一个指定的函数,并将函数的返回值收集到一个新的集合中。它能够将一个集合转换为另一个集合,新集合中的元素个数与原集合相同,但元素的类型或值可能会发生变化。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> squaredNumbers = numbers.stream().map(num -> num * num).collect(Collectors.toList());
上述代码使用 Stream API,通过调用 map() 方法对集合中的每个元素应用一个函数,并将返回的结果收集到一个新的集合中。在示例中,使用 Lambda 表达式 num -> num * num 将每个数字平方,并将结果收集到 squaredNumbers 集合中。
三、mapToInt、mapToLong、mapToDouble
mapToInt() 是 Java 中专门用于处理基本数据类型的 Stream 接口的一个方法。它将 Stream 中的元素映射为 int 类型,并返回一个 IntStream,其中包含映射的结果。
List<String> strings = Arrays.asList("1", "2", "3", "4", "5");
IntStream intStream = strings.stream().mapToInt(Integer::parseInt);
intStream.forEach(System.out::println); // 输出 1 2 3 4 5
在上述示例中,使用 mapToInt(Integer::parseInt) 将字符串转换为相应的 int 数值。然后通过 forEach() 方法遍历 IntStream 中的每个元素,并打印出结果。
使用 mapToInt() 方法可以极大地简化在 Stream 中处理基本数据类型的逻辑,避免了自动装箱和拆箱的开销,并提供了更高效的处理方式。同时,还可以使用 IntStream 提供的丰富的方法来进行进一步的处理和操作。
mapToLong、mapToDouble以上相同
四、flatMap
flatMap() 方法是 Java 中用于处理嵌套集合的 Stream 接口的一个方法。它可以将嵌套的集合结构展平为一个扁平化的流,从而方便进行进一步的处理和操作。
List<List<Integer>> nestedList = Arrays.asList(Arrays.asList(1, 2),Arrays.asList(3, 4),Arrays.asList(5, 6)
);
Stream<Integer> flattenedStream = nestedList.stream().flatMap(Collection::stream);
flattenedStream.forEach(System.out::println); // 输出 1 2 3 4 5 6
在上述示例中,nestedList 是一个包含多个嵌套列表的集合。通过使用 flatMap(Collection::stream),将每个嵌套列表转换为一个 Stream,然后将所有的 Stream 连接起来形成一个扁平化的流。最后使用 forEach() 方法遍历扁平化后的流并打印元素。
使用 flatMap() 方法可以方便地处理包含嵌套集合的数据结构,并将其展开为一个扁平化的流,使后续的处理更加便捷和灵活。这个方法在处理多层嵌套的数据结构时特别有用,可以避免繁琐的嵌套循环操作。
五、flatMapToInt、flatMapToLong、flatMapToDouble
flatMapToInt() 是 Java 中专门用于处理基本数据类型的扁平化流的 Stream 接口的一个方法。它将 Stream 中的元素映射为 IntStream 类型,并将所有的 IntStream 连接起来形成一个扁平化的流。
List<List<Integer>> nestedList = Arrays.asList(Arrays.asList(1, 2),Arrays.asList(3, 4),Arrays.asList(5, 6)
);
IntStream flattenedIntStream = nestedList.stream().flatMapToInt(innerList -> innerList.stream().mapToInt(Integer::intValue));
flattenedIntStream.forEach(System.out::println); // 输出 1 2 3 4 5 6
在上述示例中,nestedList 是一个包含多个嵌套列表的集合。通过使用 flatMapToInt(innerList -> innerList.stream().mapToInt(Integer::intValue)),将每个嵌套列表转换为一个 IntStream,然后将所有的 IntStream 连接起来形成一个扁平化的流。最后使用 forEach() 方法遍历扁平化后的流并打印元素。
使用 flatMapToInt() 方法可以方便地处理包含基本数据类型的嵌套集合,并将其展开为一个扁平化的流,使后续的处理更加便捷和灵活。这个方法在处理多层嵌套的数据结构时特别有用,可以避免繁琐的嵌套循环操作,并能够更高效地处理基本数据类型。
flatMapToLong、flatMapToDouble以上相同
六、distinct
distinct() 是 Java 中 Stream 接口的一个方法,用于去除流中重复的元素,返回一个由不同元素组成的新流。
distinct() 方法返回的新流中,元素的顺序保持与原始流中的顺序相同。它使用元素的 equals() 方法来判断是否为重复元素,因此要确保元素正确实现了 equals() 方法。
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 3, 4, 5, 5);
Stream<Integer> distinctStream = numbers.stream().distinct();
distinctStream.forEach(System.out::println); // 输出 1 2 3 4 5
在上述示例中,我们有一个包含重复元素的列表 numbers。通过使用 distinct() 方法,我们获取到一个新流 distinctStream,其中去除了重复的元素。最后使用 forEach() 方法处理新流,并打印每个元素。
注意,distinct() 方法依赖于元素的 equals() 方法来判断是否为重复元素。如果元素没有正确重写 equals() 方法,可能无法正确去除重复元素,返回的流中仍会包含重复的元素。
使用 distinct() 方法可以方便地对流中的元素进行去重操作,使得后续的处理更加准确和高效。
七、sorted
sorted() 是 Java 中 Stream 接口的一个方法,用于对流进行排序操作。它返回一个新的流,其中的元素按照自然顺序或根据指定的比较器进行排序。
List<Integer> numbers = Arrays.asList(5, 3, 1, 4, 2);
Stream<Integer> sortedStream = numbers.stream().sorted();
sortedStream.forEach(System.out::println); // 输出 1 2 3 4 5
在上述示例中,我们有一个包含整数的列表 numbers。通过使用 sorted() 方法,我们获取到一个新的流 sortedStream,其中的元素按照自然顺序进行排序。最后使用 forEach() 方法处理新流,并打印每个元素。
class Student {private String name;private int age;public Student(String name, int age) {this.name = name;this.age = age;}// getter 和 setter 方法省略@Overridepublic String toString() {return name + " - " + age;}
}List<Student> students = new ArrayList<>();
students.add(new Student("Alice", 22));
students.add(new Student("Bob", 20));
students.add(new Student("Charlie", 21));// 按照年龄升序排序
students.stream().sorted((s1, s2) -> Integer.compare(s1.getAge(), s2.getAge())).forEach(System.out::println);// 按照名称长度降序排序
students.stream().sorted((s1, s2) -> Integer.compare(s2.getName().length(), s1.getName().length())).forEach(System.out::println);
在上述示例中,有一个包含学生对象的列表 students。首先,通过传入一个比较器匿名类 (s1, s2) -> Integer.compare(s1.getAge(), s2.getAge()),使用 sorted() 方法将学生对象按照年龄升序进行排序。然后,传入另一个比较器 (s1, s2) -> Integer.compare(s2.getName().length(), s1.getName().length()),使用 sorted() 方法将学生对象按照名称长度降序进行排序。
通过定制的比较器,我们可以根据不同的排序规则和属性进行排序操作。
八、peek
peek() 是 Java 中 Stream 接口的一个中间操作方法,用于在流的处理过程中执行额外的操作,而不会改变流中的元素。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.stream().peek(System.out::println) // 打印每个元素.map(n -> n * 2) // 将每个元素乘以2.forEach(System.out::println); // 打印处理后的元素
在上述示例中,我们有一个包含整数的列表 numbers。通过使用 stream() 方法获取流,然后使用 peek() 方法提供一个消费者函数,对每个元素进行打印操作。在打印完元素后,使用 map() 方法将每个元素乘以2,最后使用 forEach() 方法打印处理后的元素。
需要注意的是,peek() 方法并不是用于修改流中的元素,而是通过回调函数执行额外的操作。它返回的仍然是原始的流,可以继续进行其他的中间操作或终端操作。
peek() 方法常用于调试、记录中间状态、查看流中的元素等场景。可以结合其他的流操作一起使用,提供更灵活的流处理。但是需要注意,它不应该用于具有副作用的操作,比如修改可变状态,因为其结果是不可预测的。
九、limit
limit() 是 Java 中 Stream 接口的一个中间操作方法,用于限制流中元素的数量,返回一个包含最多指定数量元素的新流。
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.stream().limit(3) // 限制最多3个元素.forEach(System.out::println); // 打印限制后的元素
在上述示例中,我们有一个包含整数的列表 numbers。通过使用 stream() 方法获取流,然后使用 limit() 方法限制最多只能获取3个元素。最后使用 forEach() 方法打印限制后的元素。
limit() 方法对于在大型流中处理前几个元素非常有用,可以提高性能和节省资源。
需要注意的是,limit() 方法会在满足指定数量的元素之后截断流,因此如果流中元素数量少于指定的最大数量,那么限制后的流将包含所有元素。
总结来说,limit() 方法可以用于限制流中元素数量,提供了一种简单有效的方式来处理大型数据流或控制处理的范围。
十、forEach
forEach() 是 Java 中 Stream 接口的一个终端操作方法,用于对流中的每个元素执行指定的操作。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream().forEach(System.out::println); // 打印每个元素
在上述示例中,我们有一个包含字符串的列表 names。通过使用 stream() 方法获取流,然后使用 forEach() 方法传入一个消费者函数来打印流中的每个元素。
forEach() 方法会逐个处理流中的元素,并对每个元素执行指定的操作。它是一个终端操作,表示流的处理结束,因此在调用 forEach() 方法之后不能再对流进行其他操作。
需要注意的是,forEach() 并不保证元素的处理顺序,它可能是并行执行的。如果需要按照特定的顺序处理元素,可以考虑使用 forEachOrdered() 方法。
总结来说,forEach() 方法是一个简单而方便的方式,在流中的每个元素上执行特定的操作,比如打印、记录或其他自定义操作。它是一个终端操作,用于结束流的处理并执行最终操作。
十一、forEachOrdered
forEachOrdered() 是 Java 中 Stream 接口的一个终端操作方法,用于对流中的每个元素按照顺序执行指定的操作。
与 forEach() 方法不同的是,forEachOrdered() 方法会保证按照流的遍历顺序逐个处理流中的元素,而不管流是否是并行执行的。这种保证是通过对流进行合并和排序来实现的。
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream().forEachOrdered(System.out::println); // 按顺序打印每个元素
在上述示例中,我们有一个包含字符串的列表 names。通过使用 stream() 方法获取流,然后使用 forEachOrdered() 方法传入一个消费者函数来按照顺序打印流中的每个元素。
forEachOrdered() 方法保证按照流的遍历顺序执行操作,而不管流是否是并行执行的。这对于确保按照原始顺序处理元素非常有用,特别是在并行流中。
需要注意的是,forEachOrdered() 是一个终端操作,表示流的处理结束,因此在调用该方法之后不能再对流进行其他操作。
总结来说,forEachOrdered() 方法是一个保证按顺序处理流中元素的方式,在流中的每个元素上执行特定的操作。与 forEach() 方法相比,它提供了对于并行执行的支持和顺序保证。
十二、toArray
toArray() 是 Java 中 Stream 接口的一个终端操作方法,用于将流中的元素转换为数组。
toArray() 方法将流中的元素按照流的遍历顺序转换为一个 Object 类型的数组,并返回该数组。
以下是使用 toArray() 方法的示例:
List<String> colors = Arrays.asList("Red", "Green", "Blue");
Object[] array = colors.stream().toArray();
在上述示例中,我们有一个包含字符串的列表 colors。通过使用 stream() 方法获取流,然后使用 toArray() 方法将流中的元素转换为一个 Object 类型的数组。
需要注意的是,toArray() 方法返回的是一个包含流中所有元素的数组,数组的元素类型为 Object。如果希望得到特定类型的数组,可以使用带有类型参数的 toArray() 方法,如下所示:
String[] array = colors.stream().toArray(String[]::new);
在上述示例中,我们使用 toArray(String[]::new),该方法会将流中的元素转换为一个 String 类型的数组,并返回该数组。
总结来说,toArray() 方法用于将流中的元素转换为数组。它提供了一种方便的方式来获取流中的元素集合,并以数组的形式进行处理或传递给其他方法。
十三、reduce
reduce() 是 Java 中 Stream 接口的一个终端操作方法,用于将流中的元素按照指定的操作进行归约(reduce)。
reduce() 方法使用指定的二元操作对流中的元素进行逐个归约,返回一个 Optional 对象,该对象包含归约的结果。如果流为空,则返回一个空的 Optional。
以下是使用 reduce() 方法的示例:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> sum = numbers.stream().reduce((a, b) -> a + b);
在上述示例中,我们有一个包含整数的列表 numbers。通过使用 stream() 方法获取流,然后使用 reduce() 方法传入一个对两个整数进行相加的二元操作 (a, b) -> a + b。
reduce() 方法将流中的元素按照指定的二元操作进行归约,得到一个结果。在本例中,我们将列表中的整数进行求和的归约操作。
reduce() 方法返回一个 Optional 对象,因为流可能为空。可以使用 Optional 的方法来获取归约的结果,如下所示:
int result = sum.orElse(0); // 获取归约的结果,如果为空则返回默认值 0
在上述示例中,我们使用 orElse(0) 方法从 Optional 对象中获取归约的结果,如果为空则返回默认值 0。
除了接受一个二元操作的 reduce() 方法,还有其他重载方法可以接受初始值和一个三元操作,更加灵活地进行归约的操作。
总结来说,reduce() 方法用于将流中的元素按照指定的操作进行归约。它提供了一种简单而强大的方式来处理流中的元素并生成一个结果。
十四、collect
collect() 是 Java 中 Stream 接口的一个终端操作方法,用于将流中的元素收集到一个可变容器或集合中。
Collector 是一个用于描述流元素收集过程的接口,其中包含了用于创建结果容器、收集元素和合并部分结果的方法。
以下是使用 collect() 方法的示例:
List<String> colors = Arrays.asList("Red", "Green", "Blue");
List<String> collectedList = colors.stream().collect(Collectors.toList());
在上述示例中,我们有一个包含字符串的列表 colors。通过使用 stream() 方法获取流,然后使用 collect() 方法传入 Collectors.toList(),它是一个用于收集元素到列表中的内置收集器。
collect() 方法将流中的元素按照指定的收集器进行收集,返回收集后的结果。在本例中,我们将元素收集到一个列表中。
除了 Collectors.toList(),Java 还提供了其他内置的收集器,如 toSet()(收集到集合)、toMap()(收集到映射)、joining()(连接为字符串)等。
此外,还可以通过自定义 Collector 的方式进行个性化的集合操作,例如自定义结果容器、元素收集和结果合并的逻辑。
总结来说,collect() 方法用于将流中的元素收集到一个可变容器或集合中。它提供了一种灵活且强大的方式来处理流中的元素,并生成最终的收集结果。
十五、min、max
min() 和 max() 是 Java 中 Stream 接口的终端操作方法,用于找到流中的最小值和最大值。
min() 和 max() 是 Java 中 Stream 接口的终端操作方法,用于找到流中的最小值和最大值。
以下是使用 min() 和 max() 方法的示例:
List<Integer> numbers = Arrays.asList(2, 5, 1, 3, 4);
Optional<Integer> min = numbers.stream().min(Comparator.naturalOrder());Optional<Integer> max = numbers.stream().max(Comparator.naturalOrder());
在上述示例中,我们有一个包含整数的列表 numbers。通过使用 stream() 方法获取流,在 min() 或 max() 方法中传入 Comparator.naturalOrder(),它是一个自然排序的比较器,即比较元素的自然顺序。
min() 方法返回一个 Optional 对象,包含列表中的最小元素。在本例中,返回的 Optional 包含值 1。
max() 方法同样返回一个 Optional 对象,包含列表中的最大元素。在本例中,返回的 Optional 包含值 5。
可以使用 Optional 的方法来获取最小/最大元素,如下所示:
int minValue = min.orElse(0); // 获取最小值,如果为空则返回默认值 0
int maxValue = max.orElseThrow(); // 获取最大值,如果为空则抛出异常
在上述示例中,我们分别使用 orElse(0) 和 orElseThrow() 方法从 Optional 对象中获取最小/最大元素。
如果想要自定义比较器来进行比较,可以实现自己的 Comparator 接口。
总结来说,min() 和 max() 方法用于在流中找到最小值和最大值。它们提供了一种便捷的方式来找到流元素中的极值,并以 Optional 的形式返回结果。
十六、count
count() 是 Java 中 Stream 接口的一个终端操作方法,用于计算流中元素的个数。
以下是使用 count() 方法的示例:
List<String> colors = Arrays.asList("Red", "Green", "Blue");
long count = colors.stream().count();
在上述示例中,我们有一个包含字符串的列表 colors。通过使用 stream() 方法获取流,然后使用 count() 方法计算流中元素的个数。
count() 方法返回一个 long 值,表示流中元素的个数。在本例中,返回的值为 3。
需要注意的是,count() 方法是一个终端操作,一旦调用了 count() 方法,流就会被消费一次,无法再次使用。
另外,对于大型或无界的流,count() 方法可能会消耗较长的时间,因为它需要遍历整个流来计算元素的个数。
总结来说,count() 方法用于计算流中元素的个数。它提供了一种简便的方式来获取流的大小,对于统计和判断流是否为空等场景非常有用。
十七、anyMatch、allMatch、noneMatch
anyMatch(), allMatch() 和 noneMatch() 是 Java 中 Stream 接口的终端操作方法,用于检查流中的元素是否满足特定的条件。
anyMatch() 方法用于检查至少有一个元素满足给定条件。
allMatch() 方法用于检查所有元素是否都满足给定条件。
noneMatch() 方法用于检查没有元素满足给定条件。
这些方法都接受一个 Predicate 参数,表示用于检查元素的条件。Predicate 是一个函数式接口,用于表示一个接受一个参数并返回布尔值的函数。
以下是使用 anyMatch()、allMatch() 和 noneMatch() 方法的示例:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);boolean anyMatchResult = numbers.stream().anyMatch(n -> n % 2 == 0);boolean allMatchResult = numbers.stream().allMatch(n -> n > 0);boolean noneMatchResult = numbers.stream().noneMatch(n -> n > 5);
在上述示例中,我们有一个包含整数的列表 numbers。通过使用 stream() 方法获取流,并在 anyMatch()、allMatch()、noneMatch() 方法中提供相应的条件。
anyMatch() 方法检查流中是否有至少一个元素满足给定条件。在本例中,返回的结果为 true,因为列表中存在一个偶数(2)满足条件。
allMatch() 方法检查流中的所有元素是否都满足给定条件。在本例中,返回的结果为 true,因为列表中的所有元素都大于 0。
noneMatch() 方法检查流中是否没有元素满足给定条件。在本例中,返回的结果为 true,因为列表中没有大于 5 的元素。
这些方法返回一个布尔值,表示检查的结果是否满足给定的条件。
需要注意的是,以上方法都是短路操作,即一旦确定结果是 true 或 false,就会立即停止遍历剩余的元素。
总结来说,anyMatch()、allMatch() 和 noneMatch() 方法用于检查流中的元素是否满足给定的条件。它们提供了一种简洁的方式来进行流元素的条件判断,非常适用于筛选和验证的场景。
十八、findFirst、findAny
findFirst() 和 findAny() 是 Java 中 Stream 接口的终端操作方法,用于在流中查找满足给定条件的元素。
findFirst() 方法用于查找流中的第一个满足条件的元素。
findAny() 方法用于查找流中的任意一个满足条件的元素。
以下是使用 findFirst() 和 findAny() 方法的示例:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);Optional<Integer> first = numbers.stream().findFirst();Optional<Integer> any = numbers.stream().findAny();
在上述示例中,我们有一个包含整数的列表 numbers。通过使用 stream() 方法获取流,并在 findFirst()、findAny() 方法中调用。
findFirst() 方法返回流中的第一个满足条件的元素。在本例中,返回的 Optional 包含元素 1。
findAny() 方法返回流中的任意一个满足条件的元素。在本例中,返回的 Optional 包含元素 1,因为在列表中满足条件的元素是唯一的。
需要注意的是,这两个方法都是短路操作,一旦找到满足条件的元素,就会立即停止遍历剩余的元素。
对于有序的流,findFirst() 方法通常返回流中的第一个元素,而 findAny() 方法则可以返回任意一个满足条件的元素。
对于并行流(parallel stream),对于非有序的流,findAny() 可能会比 findFirst() 更快,因为它可以在多个并行子流中寻找满足条件的元素。
总结来说,findFirst() 和 findAny() 方法用于在流中查找满足条件的元素。它们返回一个 Optional 对象,表示可能存在或可能为空的结果。在需要查找特定元素或仅需任意满足条件的元素时,这些方法非常有用。
十九、builder
在Java中,"builder"是一种设计模式,用于创建复杂对象的构造器。Builder模式允许我们逐步构建对象,并可以根据需要自定义对象的属性。
Builder模式通常包含一个用于设置属性的builder类,以及一个用于构建最终对象的builder方法链。通过使用builder模式,我们可以避免编写冗长的构造函数并处理多个可选参数。
以下是使用Builder模式的示例:
public class Person {private String name;private int age;private String address;private Person(Builder builder) {this.name = builder.name;this.age = builder.age;this.address = builder.address;}public String getName() {return name;}public int getAge() {return age;}public String getAddress() {return address;}public static class Builder {private String name;private int age;private String address;public Builder setName(String name) {this.name = name;return this;}public Builder setAge(int age) {this.age = age;return this;}public Builder setAddress(String address) {this.address = address;return this;}public Person build() {return new Person(this);}}
}
在上述示例中,我们定义了一个Person类,并使用内部静态类Builder作为Person类的构造器。Person类具有私有的构造函数,只能通过Builder来构建对象。
Builder类提供了一组用于设置属性的方法(setName,setAge,setAddress),并通过链式调用返回Builder对象。最后,Builder类提供了一个build方法,该方法利用Builder对象的属性创建一个Person对象。
通过使用Builder模式,我们可以以更清晰、简洁的方式构建对象:
Person person = new Person.Builder().setName("John").setAge(25).setAddress("123 Main St").build();
在这个示例中,我们使用Builder模式逐步构建Person对象,设置了name、age和address属性,并通过build方法创建最终的Person对象。
通过使用Builder模式,我们可以更容易地创建具有多个可选属性的对象,并且不需要在构造函数中使用大量的参数。这提供了更好的灵活性和可读性。
二十、of
在Java 8的Stream API中,"of"方法用于创建一个由指定元素组成的流。
Stream<Integer> numbers = Stream.of(1, 2, 3, 4, 5);
在这个示例中,我们使用Stream的"of"方法创建了一个包含整数元素的流。
二十一、iterate
在Java中,iterate 是Stream API中的一个静态方法,用于创建一个按照指定规则迭代生成元素的流。
iterate 方法接受两个参数:初始值和迭代函数。它会根据迭代函数对初始值进行重复应用,生成一个无限流。
以下是 iterate 方法的示例:
Stream.iterate(1, n -> n + 1).limit(5).forEach(System.out::println);
在上述示例中,我们使用 iterate 方法创建一个从1开始的自增序列流。迭代函数 n -> n + 1 将初始值加1,然后再将结果作为下一次迭代的初始值。
通过使用 limit 方法,我们限制流的大小,只取前5个元素。最后,使用 forEach 方法打印每个元素。
输出结果为
1
2
3
4
5
需要注意的是,iterate 方法生成的是无限流。如果不使用 limit 方法或其他中止操作,流将无限地生成元素。
除了上述示例中的递增序列,我们还可以根据需要使用不同的迭代函数生成不同的序列。
例如,创建一个斐波那契数列的流:
Stream.iterate(new int[]{0, 1}, fib -> new int[]{fib[1], fib[0] + fib[1]}).limit(10).forEach(fib -> System.out.print(fib[0] + " "));
输出结果为:
0 1 1 2 3 5 8 13 21 34
在这个示例中,我们使用一个整数数组来表示每个斐波那契数列元素。迭代函数会根据前两个元素的值计算出下一个元素。
总结来说,iterate 方法允许我们根据指定的迭代函数生成无限流。通过结合使用流的其他中止操作,我们可以对生成的元素进行限制、过滤、映射等操作。这样我们就可以便捷地生成不同规则的序列或重复数据。
二十二、generate
在Java中,generate 是Stream API中的一个静态方法,用于创建一个由指定生成函数生成元素的流。
generate 方法接受一个无参的生成函数作为参数,并通过重复调用该函数来生成流的元素。生成函数不接受任何输入参数,只返回一个新的元素。
以下是 generate 方法的示例:
Stream.generate(() -> "Hello").limit(5).forEach(System.out::println);
在上述示例中,我们使用 generate 方法创建了一个由字符串 “Hello” 组成的流。生成函数 () -> “Hello” 在每次调用时都返回字符串 “Hello”。
通过使用 limit 方法,我们限制流的大小,只取前5个元素。最后,使用 forEach 方法打印每个元素。
输出结果为:
Hello
Hello
Hello
Hello
Hello
需要注意的是,generate 方法生成的是无限流。如果不使用 limit 方法或其他中止操作,流将无限地生成元素。
除了简单地生成固定值的流,我们还可以根据需要生成更复杂的元素。
例如,生成一个随机整数的流:
Stream.generate(() -> new Random().nextInt(100)).limit(5).forEach(System.out::println);
输出结果为:
76
41
62
89
14
在这个示例中,我们使用生成函数 () -> new Random().nextInt(100) 创建一个返回随机整数 (0到99之间) 的流。
总结来说,generate 方法允许我们根据指定的生成函数生成流。通过结合使用流的其他中止操作,我们可以对生成的元素进行限制、过滤、映射等操作。这样我们就可以便捷地生成根据不同规则生成元素的流。
二十三、concat
在Java中,concat 是Stream API中的一个静态方法,用于合并两个流。
concat 方法接受两个流作为参数,并返回一个新的流,其中包含两个输入流中的所有元素。
以下是 concat 方法的示例:
Stream<Integer> stream1 = Stream.of(1, 2, 3);
Stream<Integer> stream2 = Stream.of(4, 5, 6);Stream<Integer> combinedStream = Stream.concat(stream1, stream2);
combinedStream.forEach(System.out::println);
在上述示例中,我们创建了两个整数流 stream1 和 stream2,分别包含数字 1 到 3 和 4 到 6。
然后,我们使用 concat 方法合并这两个流,并将结果赋给了新的流 combinedStream。
最后,我们通过 forEach 方法遍历并打印合并后的流中的所有元素。
输出结果为:
1
2
3
4
5
6
需要注意的是,concat 方法将两个流合并成一个新的流,并保持了元素的顺序。
除了合并两个流之外,concat 方法还可以与其他流进行串联,以实现更多的组合。
例如,串联多个流:
Stream<Integer> stream1 = Stream.of(1, 2, 3);
Stream<Integer> stream2 = Stream.of(4, 5, 6);
Stream<Integer> stream3 = Stream.of(7, 8, 9);Stream<Integer> combinedStream = Stream.concat(Stream.concat(stream1, stream2), stream3);
combinedStream.forEach(System.out::println);
在这个示例中,我们将三个整数流 stream1、stream2 和 stream3 串联起来,得到一个包含所有元素的新流。
输出结果为:
1
2
3
4
5
6
7
8
9
总结来说,concat 方法允许我们合并两个流来创建一个包含两个输入流中所有元素的新流。它提供了一种简便的方式来组合多个流。
总结
@作者:加辣椒了吗?
简介:憨批大学生一枚,喜欢在博客上记录自己的学习心得,也希望能够帮助到你们!