一、Stream流引入

Lambda表达式,基于Lambda所带来的函数式编程,又引入了一个全新的Stream概念,用于解决集合类库既有的鼻端。

现有一个需求:

将list集合中姓张的元素过滤到一个新的集合中
然后将过滤出来的姓张的元素中,再过滤出来长度为3的元素,存储到一个新的集合中
1.用常规方法解决需求

  1. // 已知的知识来解决需求
  2. List<String> list1 = new ArrayList<>();
  3. list1.add("张老三");
  4. list1.add("张小三");
  5. list1.add("李四");
  6. list1.add("赵五");
  7. list1.add("张六");
  8. list1.add("王八");
  9. ArrayList<String> list2 = new ArrayList<>();
  10. // 1.将list集合中姓张的元素过滤到一个新的集合中
  11. for(String name : list1){
  12. if(name.startsWith("张")){
  13. list2.add(name);
  14. }
  15. }
  16. ArrayList list3 = new ArrayList();
  17. for (String name : list2) {
  18. if (name.length() == 3){
  19. list3.add(name);
  20. }
  21. }
  22. System.out.println(list3);
  23. 输出结果:
  24. [张老三, 张小三]

2.用Stream流操作集合,获取流,过滤操作,打印输出

  1. list1.stream().filter(name->name.startsWith("张")).filter(name->name.length()==3).forEach(name->System.out.println("符合条件的姓名:" + name));

二、Stream流的格式

  1. Stream<T> filter(Predicate<? super T> predicate);
  2. -----> 参数:public interface Predicate<T> (函数式接口)
  3. ----> 抽象方法:boolean test(T t);
  4. -----> 参数:public interface Consumer<T> (函数式接口)
  5. ----> 抽象方法:boolean test(T t);

整体代码看来:流式思想 类似于 工厂车间的“流水线”

三、获取流

根据集合来获取:
根据Collection获取流:
Collection接口中有一个stream()方法,可以获取流
**default Stream<E> stream()**

  1. 根据List获取流
  2. 根据Set获取流
  3. 根据Map获取流
  • 根据Map集合的键来获取流
  • 根据Map集合的值获取流
  • 根据Map集合的键值对对象获取流
  1. 根据数组获取流

    代码演示:

    1.根据List集合获取流

    1. // 创建List集合
    2. List<String> list = new ArrayList<>();
    3. list.add("张老三");
    4. list.add("张小三");
    5. list.add("李四");
    6. list.add("赵五");
    7. list.add("张六");
    8. list.add("王八");
    9. Stream<String> stream1 = list.stream();

    2.根据Set集合获取流

    1. // 创建List集合
    2. Set<String> set = new HashSet<>();
    3. list.add("张老三");
    4. list.add("张小三");
    5. list.add("李四");
    6. list.add("赵五");
    7. list.add("张六");
    8. list.add("王八");
    9. Stream<String> stream2 = set.stream();

    3.根据Map集合获取流

    1. // 创建Map集合
    2. Map<Integer,String> map = new HashMap<>();
    3. map.put(1,"张老三");
    4. map.put(2,"张小三");
    5. map.put(3,"李四");
    6. map.put(4,"赵五");
    7. map.put(5,"张六");
    8. map.put(6,"王八");
    9. // 3.1根据Map集合的键获取流
    10. Set<Integer> map1 = map.keySet();
    11. Stream<Integer> stream3 = map1.stream();
    12. // 3.2根据Map集合的值获取流
    13. Collection<String> map2 = map.values();
    14. Stream<String> stream4 = map2.stream();
    15. // 3.3根据Map集合的键值对对象获取瑞
    16. Set<Map.Entry<Integer, String>> map3 = map.entrySet();
    17. Stream<Map.Entry<Integer, String>> stream5 = map3.stream();

    4.根据数组获取流

    1. // 根据数组获取流
    2. String[] arr = {"张颜宇","张三","李四","赵五","刘六","王七"};
    3. Stream<String> stream6 = Stream.of(arr);


    四、Stream流的常用方法

    Stream流的常用方法:
    终结方法:返回值类型不再是Stream接口本身类型的方法,例如:forEach方法和count方法
    非终结方法/延迟方法:返回值类型仍然是Stream接口自身类型的方法,除了终结方法都是延迟方法。例如:filter,limit,skip,map,conat

方法名称 方法作用 方法种类 是否支持链式调用
count 统计个数 终结方法
forEach 逐一处理 终结方法
filter 过滤 函数拼接
limit 取用前几个 函数拼接
skip 跳过前几个 函数拼接
map 映射 函数拼接
concat 组合 函数拼接

方法演示:

1.count方法:

long count (); 统计流中的元素,返回long类型数据

  1. List<String> list = new ArrayList<>();
  2. list.add("张老三");
  3. list.add("张小三");
  4. list.add("李四");
  5. list.add("赵五");
  6. list.add("张六");
  7. list.add("王八");
  8. long count = list.stream().count();
  9. System.out.println("集合中的元素个数是:" + count);
  10. 输出结果:
  11. 集合中的元素个数是:6

2.filter方法:

Stream filter(Predicate<? super ?> predicate); 过滤出满足条件的元素
参数Predicate:函数式接口,抽象方法:boolean test (T t)
Predicate接口:是一个判断接口

  1. // 获取stream流
  2. Stream<String> stream = Stream.of("张老三", "张小三", "李四", "赵五", "刘六", "王七");
  3. // 需求:过去出姓张的元素
  4. stream.filter((String name)->{
  5. return name.startsWith("张");
  6. }).forEach((String name)->{
  7. System.out.println("流中的元素" + name);
  8. });

3.forEach方法

void forEach(Consumer<? super T> action):逐一处理流中的元素
参数 Consumer<? super T> action:函数式接口,只有一个抽象方法:void accept(T t);

注意:
1.此方法并不保证元素的逐一消费动作在流中是有序进行的(元素可能丢失)
2.Consumer是一个消费接口(可以获取流中的元素进行遍历操作,输出出去),可以使用Lambda表达式

  1. List<String> list = new ArrayList<>();
  2. list.add("张老三");
  3. list.add("张小三");
  4. list.add("李四");
  5. list.add("赵五");
  6. list.add("张六");
  7. list.add("王八");
  8. // 函数模型:获取流 --> 注意消费流中的元素
  9. list.stream().forEach(name->System.out.println(name));
  10. 输出结果:
  11. 张老三
  12. 张小三
  13. 李四
  14. 赵五
  15. 张六
  16. 王八

4.limit方法

Stream limit(long maxSize); 取用前几个元素
注意:
参数是一个long 类型,如果流的长度大于参数,则进行截取;否则不进行操作

  1. // 获取流的长度
  2. Stream<String> stream1 = Stream.of("张老三", "张小三", "李四", "赵五", "刘六", "王七");
  3. // 需求:保留前三个元素
  4. stream1.limit(3).forEach((String name)->{
  5. System.out.println("流中的前三个元素是:" + name);
  6. });
  7. 输出结果:
  8. 流中的前三个元素是:张老三
  9. 流中的前三个元素是:张小三
  10. 流中的前三个元素是:李四

5.map方法

Stream map(Function<? super T,? exception R> mapper;
参数Function:函数式接口,抽象方法:R apply(T t);
Function:其实就是一个类型转换接口(T和R的类型可以一致,也可以不一致)

  1. // 获取Stream流
  2. Stream<String> stream1 = Stream.of("11","22","33","44","55");
  3. // 需求:把stream1流中的元素转换为int类型
  4. stream1.map(s->Integer.parseInt(s)// 将String类型的s进行转换为Integer类型的元素,并返回
  5. ).forEach(i->
  6. System.out.println(i) // 将转换后的int类型的元素逐一输出
  7. );
  8. 输出结果:
  9. 11
  10. 22
  11. 33
  12. 44
  13. 55

6.skip方法

Stream skip(long n); 跳过前几个元素
注意:
如果流的当前长度大于n,则跳过前n个,否则将会得到一个长度为0的空流

  1. // 获取stream流
  2. Stream<String> stream = Stream.of("张老三", "张小三", "李四", "赵五", "刘六", "王七");
  3. stream.skip(3).forEach(name->System.out.println("跳过前三个,打印剩下的" + name));
  4. 输出结果:
  5. 跳过前三个,打印剩下的赵五
  6. 跳过前三个,打印剩下的刘六
  7. 跳过前三个,打印剩下的王七

7.concat方法

public static Stream concat(Stream<? extends T> a, Stream<? extends T> b)
—> 合并两个流

  1. Stream<String> stream1 = Stream.of("11","22","33","44","55");
  2. Stream<String> stream2 = Stream.of("张颜宇", "张三", "李四", "赵五", "刘六", "王七");
  3. // 需求:合并两个流
  4. Stream<String> stream = Stream.concat(stream1,stream2);
  5. stream.forEach( name->System.out.print(name));
  6. 输出结果:
  7. 1122334455张颜宇张三李四赵五刘六王七

五、收集Stream流

Stream流中提供了一个方法,可以把流中的数据收集到单例集合中
R collect(Collector<? super T, A, R> collector); 把流中的数据手机到单列集合中
返回值类型是R。R指定为什么类型,就是手机到什么类型的集合
参数Collector<? super T, A, R>中的R类型,决定把流中的元素收集到哪个集合中
参数Collector如何得到 ?,可以使用 java.util.stream.Collectors工具类中的静态方法:
- public static Collector> toList():转换为List集合
- public static Collector> toSet() :转换为Set集合

  1. List<String> list2 = new ArrayList<>();
  2. list2.add("张老三");
  3. list2.add("张小三");
  4. list2.add("李四");
  5. list2.add("赵五");
  6. list2.add("张六");
  7. list2.add("王八");
  8. // 需求:过滤出姓张的并且长度为3的元素
  9. Stream<String> stream = list2.stream().filter(name -> name.startsWith("张")).filter(name -> name.length() == 3);
  10. // stream 收集到单列集合中
  11. List<String> list = stream.collect(Collectors.toList());
  12. System.out.println(list);
  13. // stream 手机到单列集合中
  14. Set<String> set = stream.collect(Collectors.toSet());
  15. System.out.println(set);

六、异常

在 Java 中一个异常的产生,主要有如下三种原因:

  1. Java 内部错误发生异常,Java 虚拟机产生的异常。
  2. 编写的程序代码中的错误所产生的异常,例如空指针异常、数组越界异常等。
  3. 通过 throw 语句手动生成的异常,一般用来告知该方法的调用者一些必要信息。
  • Java 通过面向对象的方法来处理异常。在一个方法的运行过程中,如果发生了异常,则这个方法会产生代表该异常的一个对象,并把它交给运行时的系统,运行时系统寻找相应的代码来处理这一异常
  • 我们把生成异常对象,并把它提交给运行时系统的过程称为拋出(throw)异常。运行时系统在方法的调用栈中查找,直到找到能够处理该类型异常的对象,这一个过程称为捕获(catch)异常。
  1. 运行时异常都是 RuntimeException 类及其子类异常,如 NullPointerException、IndexOutOfBoundsException 等,这些异常是不检查异常,程序中可以选择捕获处理,也可以不处理。这些异常一般由程序逻辑错误引起,程序应该从逻辑角度尽可能避免这类异常的发生。
  2. 非运行时异常是指 RuntimeException 以外的异常,类型上都属于 Exception 类及其子类。从程序语法角度讲是必须进行处理的异常,如果不处理,程序就不能编译通过。如 IOException、ClassNotFoundException 等以及用户自定义的 Exception 异常(一般情况下不自定义检查异常)。

运行时异常

异常类型 说明
ArithmeticException 算术错误异常,如以零做除数
ArraylndexOutOfBoundException 数组索引越界
ArrayStoreException 向类型不兼容的数组元素赋值
ClassCastException 类型转换异常
IllegalArgumentException 使用非法实参调用方法
lIIegalStateException 环境或应用程序处于不正确的状态
lIIegalThreadStateException 被请求的操作与当前线程状态不兼容
IndexOutOfBoundsException 某种类型的索引越界
NullPointerException 尝试访问 null 对象成员,空指针异常
NegativeArraySizeException 再负数范围内创建的数组
NumberFormatException 数字转化格式异常,比如字符串到 float 型数字的转换无效
TypeNotPresentException 类型未找到

非运行时异常

异常类型 说明
ClassNotFoundException 没有找到类
IllegalAccessException 访问类被拒绝
InstantiationException 试图创建抽象类或接口的对象
InterruptedException 线程被另一个线程中断
NoSuchFieldException 请求的域不存在
NoSuchMethodException 请求的方法不存在
ReflectiveOperationException 与反射有关的异常的超类