您的位置:首页 > 教育 > 锐评 > 北京市建设工程信息网ic卡_免费网页制作的网站_广州网站关键词排名_教育培训机构加盟

北京市建设工程信息网ic卡_免费网页制作的网站_广州网站关键词排名_教育培训机构加盟

2025/4/4 14:27:30 来源:https://blog.csdn.net/qq_52122048/article/details/142853245  浏览:    关键词:北京市建设工程信息网ic卡_免费网页制作的网站_广州网站关键词排名_教育培训机构加盟
北京市建设工程信息网ic卡_免费网页制作的网站_广州网站关键词排名_教育培训机构加盟

Java之stream流的详细解析一-CSDN博客(以下均参考这个)

stream:创建流(Arraylist自带了.stream就行)->中间操作(.filter)->终结操作(.foreach)/收集操作(.collect) 

public class StreamDemo {public static void main(String[] args) {//集合的批量添加ArrayList<String> list1 = new ArrayList<>(Arrays.asList("张三丰", "张无忌", "张翠山"));//Stream流list1.stream().filter(s->s.startsWith("张")).filter(s->s.length() == 3).forEach(s-> System.out.println(s));list1.stream().filter(s->s.endsWith("丰")).forEach(s-> System.out.println(s));
//        ArrayList<String>list2=(ArrayList<String>) list1.stream().filter(s->s.endsWith("丰"));ArrayList<String> list2 = list1.stream().filter(s -> s.endsWith("丰")).collect(Collectors.toCollection(ArrayList::new));
//.collect(Collectors.toCollection(ArrayList::new)):将流的结果收集到一个新的 ArrayList 中。
//        Collectors.toCollection(...):这是 Collectors 类中的一个方法,它接收一个工厂方法(通常是集合的构造函数引用),并将流 (Stream) 中的元素收集到该集合类型中。它允许你指定要收集到哪种类型的集合中。
//ArrayList::new:这是 ArrayList 构造方法的引用,等价于 new ArrayList<>()。它表示使用 ArrayList 的无参构造函数来创建一个新的 ArrayList 实例。list2.forEach(s-> System.out.println(s));Stream<String> list3=Stream.concat(list1.stream(),list2.stream());list3.forEach(s-> System.out.println("---------"+s));}
}
注意:
//集合的批量添加 jdk8只能用aslist 之后才能用listof
ArrayList<String> list1 = new ArrayList<>(Arrays.asList("张三丰", "张无忌", "张翠山"));

stream那些操作都是变成stream流了

运行结果:

终结操作:

import java.util.ArrayList;
import java.util.function.Consumer;/*** 功能:* 作者:IT伟* 日期:2024/10/11 14:31*/
public class MyStream5 {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();list.add("张三丰");list.add("张无忌");list.add("张翠山");list.add("王二麻子");list.add("张良");list.add("谢广坤");method1(list);//        long count():返回此流中的元素数long count = list.stream().count();System.out.println(count);}private static void method1(ArrayList<String> list) {//  void forEach(Consumer action):对此流的每个元素执行操作//  Consumer接口中的方法void accept(T t):对给定的参数执行此操作//在forEach方法的底层,会循环获取到流中的每一个数据.//并循环调用accept方法,并把每一个数据传递给accept方法//s就依次表示了流中的每一个数据.//所以,我们只要在accept方法中,写上处理的业务逻辑就可以了.list.stream().forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}});//        上面等同于lambda的:
//         list.stream().forEach(
//                s -> System.out.println(s)
//        );System.out.println("====================");//lambda表达式的简化格式//是因为Consumer接口中,只有一个accept方法list.stream().forEach((String s)->{System.out.println(s);});System.out.println("====================");//lambda表达式还是可以进一步简化的.list.stream().forEach(s->System.out.println(s));}
}

结果:

张三丰
张无忌
张翠山
王二麻子
张良
谢广坤
====================
张三丰
张无忌
张翠山
王二麻子
张良
谢广坤
====================
张三丰
张无忌
张翠山
王二麻子
张良
谢广坤
6Process finished with exit code 0

收集操作:

// toList和toSet方法演示
public class MyStream7 {public static void main(String[] args) {ArrayList<Integer> list1 = new ArrayList<>();for (int i = 1; i <= 10; i++) {list1.add(i);}list1.add(10);list1.add(10);list1.add(10);list1.add(10);list1.add(10);//filter负责过滤数据的.//collect负责收集数据.//获取流中剩余的数据,但是他不负责创建容器,也不负责把数据添加到容器中.//Collectors.toList() : 在底层会创建一个List集合.并把所有的数据添加到List集合中.List<Integer> list = list1.stream().filter(number -> number % 2 == 0).collect(Collectors.toList());System.out.println(list);Set<Integer> set = list1.stream().filter(number -> number % 2 == 0).collect(Collectors.toSet());System.out.println(set);}
}
//结果
[2, 4, 6, 8, 10, 10, 10, 10, 10, 10]
[2, 4, 6, 8, 10]

有难度例子:

因为本身给的是key和value一起,所以需要先切割(,而且因为切割得到的还是字符串,转成数字),看最下面那个map操作即可

/**Stream流的收集方法 toMap方法演示创建一个ArrayList集合,并添加以下字符串。字符串中前面是姓名,后面是年龄"zhangsan,23""lisi,24""wangwu,25"保留年龄大于等于24岁的人,并将结果收集到Map集合中,姓名为键,年龄为值*/
public class MyStream8 {public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();//map不能有相同的keylist.add("zhangsan,23");list.add("lisi,24");list.add("wangwu,25");
//测试是否这样做正确list.stream().filter(s -> {String[] split = s.split(",");int age = Integer.parseInt(split[1]);return age >= 24;//必须要有返回值 这是过滤条件 并不是只返回age值给stream}).forEach(System.out::println);System.out.println("====================");//需要加s->xx,先传进来list.stream().filter(s -> {String[] split = s.split(",");int age = Integer.parseInt(split[1]);return age >= 24;}).forEach(s-> System.out.println(s));System.out.println("====================");Map<String, Integer> map = list.stream().filter(s -> {String[] split = s.split(",");int age = Integer.parseInt(split[1]);return age >= 24;}//   collect方法只能获取到流中剩余的每一个数据.//在底层不能创建容器,也不能把数据添加到容器当中//Collectors.toMap 创建一个map集合并将数据添加到集合当中// s 依次表示流中的每一个数据//第一个lambda表达式就是如何获取到Map中的键//第二个lambda表达式就是如何获取Map中的值).collect(Collectors.toMap(s -> s.split(",")[0],s -> Integer.parseInt(s.split(",")[1]) ));System.out.println(map);}
lisi,24
wangwu,25
====================
lisi,24
wangwu,25
====================
{lisi=24, wangwu=25}

流操作本身不会创建容器或将数据添加到容器中。如果你需要将流的结果存入某个容器中,必须使用诸如 collect 这样的终端操作。

//在底层不能创建容器,也不能把数据添加到容器当中:

在流操作中,Stream 本身是不会直接创建或修改底层集合的。也就是说,Stream 的中间操作(如 filtermap 等)不会像传统的循环那样直接往一个集合里添加数据。流的设计哲学是惰性求值和不可变性,所有中间操作只是定义了对数据的处理方式,只有在执行终端操作(如 collectforEach 等)时,流中的数据才会被实际处理或收集。

更具体的说明:

  1. 流的中间操作不创建或修改集合

    • 当你执行诸如 filter()map()sorted() 等中间操作时,流只是在逻辑上“准备”好这些操作,但并不实际执行,也不会修改或创建集合。
    • 这些中间操作都是惰性求值的,只有当终端操作(如 collect()forEach())被调用时,流才会被消耗。
  2. 终端操作决定了数据的去向

    • 比如,collect(Collectors.toList())collect(Collectors.toCollection(ArrayList::new)) 是终端操作,它们会在流的末端实际执行,并将流中的数据收集到某个容器中。
    • 在此之前,流不会修改任何已有的容器,也不会创建新的容器。流的数据是不可变的。
  3. 底层不能创建或修改容器

    • 这意味着流的运算是在已有的数据上进行处理,但不会通过流的中间操作来创建新的集合,除非你明确通过终端操作(如 collect)来收集结果。
    • 如果你希望将流的结果放入某个集合中,需要通过 collect() 或类似的操作来实现。

  实操:Java之Stream流及方法引用的详细解析二-CSDN博客

interface Printable {void printString(String s);
}public class PrintableDemo {public static void main(String[] args) {//在主方法中调用usePrintable方法
//        usePrintable((String s) -> {
//            System.out.println(s);
//        });//Lambda简化写法usePrintable(s -> System.out.println(s));//方法引用usePrintable(System.out::println);}private static void usePrintable(Printable p) {p.printString("爱生活爱Java");}
}
爱生活爱Java
爱生活爱Java

不用重写接口方法吗

在 Java 中,使用 Lambda 表达式方法引用 的时候,你不需要显式地重写函数式接口中的方法。这是因为 Lambda 表达式方法引用 已经隐式地实现了函数式接口中的抽象方法。

函数式接口的特点:

  • 函数式接口 是指仅有一个抽象方法的接口,通常会用 @FunctionalInterface 注解来标识(虽然不加注解也是函数式接口)。
  • 函数式接口的最大优势就是可以通过 Lambda 表达式方法引用 来简化实现。

在你的例子中,Printable 是一个函数式接口,它只有一个抽象方法 printString(String s),所以你可以使用 Lambda 表达式或方法引用来简化其实现。

为什么不需要重写接口方法?

通常,在传统的实现方式中,类需要通过 implements 关键字来实现接口,并且显式地重写接口中的方法,如下所示:

public class MyPrintable implements Printable {

@Override

public void printString(String s) { System.out.println(s); } }

然后你会通过创建类的实例来使用该实现:

Printable p = new MyPrintable();

p.printString("爱生活爱Java");

然而,Lambda 表达式方法引用 本质上已经是对接口中唯一抽象方法的实现,Java 编译器能够根据上下文推断出该方法的签名,因此不需要显式创建类或重写方法。

例如:

usePrintable(s -> System.out.println(s)); // 使用 Lambda 表达式

在这个例子中,s -> System.out.println(s)Printable 接口的 printString(String s) 方法的实现,Java 编译器会自动将这个 Lambda 表达式理解为 printString 方法的实现。

再例如,使用方法引用:

usePrintable(System.out::println); // 使用方法引用

System.out::println 是对 System.out.println(String) 方法的引用,而这个方法的签名与 printString(String s) 完全匹配,因此编译器会自动将其作为 printString 方法的实现。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com