1.8stream流

1.8Stream流

1.特性

  • 不是数据结构,不会保存数据
  • 不会修改源数据,每次流操作返回的都是一个流对象
  • 惰性操作,流在中间处理过程中会先将操作记录不会立即执行,需要等到执行终止操作时才会进行实际计算

2.API操作分类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tMcdCeD3-1686273643421)(C:\Users\10059\AppData\Roaming\Typora\typora-user-images\image-20220118110314415.png)]

  • 中间操作
    • 无状态操作:指该操作不受之前元素的影响
    • 有状态操作:指该操作只有拿到所有元素之后才能继续下去
  • 终止操作
    • 非短路操作:指必须处理所有元素才能返回最终结果
    • 短路操作:指存在符合条件的元素就能返回最终结果

3.API具体用法

(1)创建Stream流

①使用集合下的 stream() 和 parallelStream() 方法
public class StreamLearn {

    public static List<Integer> integerList = new ArrayList<>();

    static {
        integerList.add(1);
        integerList.add(2);
        integerList.add(3);
        integerList.add(4);
        integerList.add(5);
    }

    public static void main(String[] args) {
        List<Integer> integerList = StreamLearn.integerList;
        //1.Collection的stream()parallelStream()创建流
        integerList.stream().filter(a->a>2).forEach(System.out::println);
        integerList.parallelStream().filter(a->a>2).forEach(a-> System.out.println(Thread.currentThread().getName()+"-"+a));
    }

}
②使用Arrays的 stream() 方法
Integer[] nums = new Integer[]{1,2,3,4,5};
Stream<Integer> stream = Arrays.stream(nums);
③使用Stream的of(),iterable(),generate() 方法
Stream<Integer> stream = Stream.of(1,2,3,4,5,6);
 
Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 2).limit(6);
stream2.forEach(System.out::println); // 0 2 4 6 8 10
 
Stream<Double> stream3 = Stream.generate(Math::random).limit(2);
stream3.forEach(System.out::println);

(2)中间操作

①筛选与切片:filter,limit,skip,distinct
  • filter:过滤元素
  • distinct:根据hashCode()和equals()方法去重
  • limit:获取前n个元素
  • skip:跳过前n个元素
/**
 * @author zhangshiqin
 * @date 2022/1/18 - 14:11
 * @description:
 */
public class StreamLearn {

    public static List<Integer> integerList = new ArrayList<>();

    static {
        integerList.add(1);
        integerList.add(2);
        integerList.add(3);
        integerList.add(4);
        integerList.add(5);
        integerList.add(5);
    }

    public static void main(String[] args) {
        List<Integer> integerList = StreamLearn.integerList;

        integerList.stream().distinct().filter(a->a>3).skip(1).limit(3).forEach(System.out::println);
    }

}
②映射:map,flatMap
  • map:接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
  • flatMap:接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。
/**
 * @author zhangshiqin
 * @date 2022/1/18 - 14:11
 * @description:
 */
public class StreamLearn {

    public static void main(String[] args) {
        List<StreamLearn> streamLearnList = StreamLearn.streamLearnList;

        //map
        streamLearnList.stream().map(streamLearn -> streamLearn.getName()).forEach(System.out::println);
        //flatMap
        List<String> flatMapResult = streamLearnList.stream().flatMap(streamLearn -> Stream.of(streamLearn.getName())).collect(Collectors.toList());
    }

    public static List<Integer> integerList = new ArrayList<>();

    public static List<StreamLearn> streamLearnList = new ArrayList<>();


    //初始化数据
    static {
        integerList.add(1);
        integerList.add(2);
        integerList.add(3);
        integerList.add(4);
        integerList.add(5);
        integerList.add(5);

        streamLearnList.add(new StreamLearn("james"));
        streamLearnList.add(new StreamLearn("wade"));
        streamLearnList.add(new StreamLearn("davis"));
        streamLearnList.add(new StreamLearn("curry"));
        streamLearnList.add(new StreamLearn("jordan"));
        streamLearnList.add(new StreamLearn("kobe"));
    }

    private String name;

    public StreamLearn(String name) {
        this.name = name;
    }

    public static List<Integer> getIntegerList() {
        return integerList;
    }

    public static void setIntegerList(List<Integer> integerList) {
        StreamLearn.integerList = integerList;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

}
③排序:sorted
  • sorted():自然排序,流中元素需实现Comparable接口
  • sorted(Comparator com):比较器排序,自定义Comparator比较器
List<String> list = Arrays.asList("aa", "ff", "dd");
//String 类自身已实现Compareable接口
list.stream().sorted().forEach(System.out::println);// aa dd ff
 
Student s1 = new Student("aa", 10);
Student s2 = new Student("bb", 20);
Student s3 = new Student("aa", 30);
Student s4 = new Student("dd", 40);
List<Student> studentList = Arrays.asList(s1, s2, s3, s4);
 
//自定义排序:先按姓名升序,姓名相同则按年龄升序
studentList.stream().sorted(
        (o1, o2) -> {
            if (o1.getName().equals(o2.getName())) {
                return o1.getAge() - o2.getAge();
            } else {
                return o1.getName().compareTo(o2.getName());
            }
        }
).forEach(System.out::println);
④消费:peek
  • peek:和map类似,但是peek传入的是一个consumer
Student s1 = new Student("aa", 10);
Student s2 = new Student("bb", 20);
List<Student> studentList = Arrays.asList(s1, s2);
 
studentList.stream()
        .peek(o -> o.setAge(100))
        .forEach(System.out::println);   
 
//结果:
Student{name='aa', age=100}
Student{name='bb', age=100}            

(3)终止操作

①匹配、聚合操作:allMatch,noMatch,anyMatch,findFirst,findAny,count,max,min
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
 
boolean allMatch = list.stream().allMatch(e -> e > 10); //false
boolean noneMatch = list.stream().noneMatch(e -> e > 10); //true
boolean anyMatch = list.stream().anyMatch(e -> e > 4);  //true
 
Integer findFirst = list.stream().findFirst().get(); //1
Integer findAny = list.stream().findAny().get(); //1
 
long count = list.stream().count(); //5
Integer max = list.stream().max(Integer::compareTo).get(); //5
Integer min = list.stream().min(Integer::compareTo).get(); //1
②约简操作:reduce
  • Optional reduce(BinaryOperator accumulator):第一次执行时,accumulator函数的第一个参数为流中的第一个元素,第二个参数为流中元素的第二个元素;第二次执行时,第一个参数为第一次函数执行的结果,第二个参数为流中的第三个元素;依次类推。
  • T reduce(T identity, BinaryOperator accumulator):流程跟上面一样,只是第一次执行时,accumulator函数的第一个参数为identity,而第二个参数为流中的第一个元素。
  • U reduce(U identity,BiFunction<U, ? super T, U> accumulator,BinaryOperator combiner):在串行流(stream)中,该方法跟第二个方法一样,即第三个参数combiner不会起作用。在并行流(parallelStream)中,我们知道流被fork join出多个线程进行执行,此时每个线程的执行流程就跟第二个方法reduce(identity,accumulator)一样,而第三个参数combiner函数,则是将每个线程的执行结果当成一个新的流,然后使用第一个方法reduce(accumulator)流程进行规约。
//经过测试,当元素个数小于24时,并行时线程数等于元素个数,当大于等于24时,并行时线程数为16
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24);
 
Integer v = list.stream().reduce((x1, x2) -> x1 + x2).get();
System.out.println(v);   // 300
 
Integer v1 = list.stream().reduce(10, (x1, x2) -> x1 + x2);
System.out.println(v1);  //310
 
Integer v2 = list.stream().reduce(0,
        (x1, x2) -> {
            System.out.println("stream accumulator: x1:" + x1 + "  x2:" + x2);
            return x1 - x2;
        },
        (x1, x2) -> {
            System.out.println("stream combiner: x1:" + x1 + "  x2:" + x2);
            return x1 * x2;
        });
System.out.println(v2); // -300
 
Integer v3 = list.parallelStream().reduce(0,
        (x1, x2) -> {
            System.out.println("parallelStream accumulator: x1:" + x1 + "  x2:" + x2);
            return x1 - x2;
        },
        (x1, x2) -> {
            System.out.println("parallelStream combiner: x1:" + x1 + "  x2:" + x2);
            return x1 * x2;
        });
System.out.println(v3); //197474048
③收集操作:collect
  • Collects.toList()
  • Collects.toSet()
  • Collects.toMap()
Student s1 = new Student("aa", 10,1);
Student s2 = new Student("bb", 20,2);
Student s3 = new Student("cc", 10,3);
List<Student> list = Arrays.asList(s1, s2, s3);
 
//装成list
List<Integer> ageList = list.stream().map(Student::getAge).collect(Collectors.toList()); // [10, 20, 10]
 
//转成set
Set<Integer> ageSet = list.stream().map(Student::getAge).collect(Collectors.toSet()); // [20, 10]
 
//转成map,注:key不能相同,否则报错
Map<String, Integer> studentMap = list.stream().collect(Collectors.toMap(Student::getName, Student::getAge)); // {cc=10, bb=20, aa=10}
 
//字符串分隔符连接
String joinName = list.stream().map(Student::getName).collect(Collectors.joining(",", "(", ")")); // (aa,bb,cc)
 
//聚合操作
//1.学生总数
Long count = list.stream().collect(Collectors.counting()); // 3
//2.最大年龄 (最小的minBy同理)
Integer maxAge = list.stream().map(Student::getAge).collect(Collectors.maxBy(Integer::compare)).get(); // 20
//3.所有人的年龄
Integer sumAge = list.stream().collect(Collectors.summingInt(Student::getAge)); // 40
//4.平均年龄
Double averageAge = list.stream().collect(Collectors.averagingDouble(Student::getAge)); // 13.333333333333334
// 带上以上所有方法
DoubleSummaryStatistics statistics = list.stream().collect(Collectors.summarizingDouble(Student::getAge));
System.out.println("count:" + statistics.getCount() + ",max:" + statistics.getMax() + ",sum:" + statistics.getSum() + ",average:" + statistics.getAverage());
 
//分组
Map<Integer, List<Student>> ageMap = list.stream().collect(Collectors.groupingBy(Student::getAge));
//多重分组,先根据类型分再根据年龄分
Map<Integer, Map<Integer, List<Student>>> typeAgeMap = list.stream().collect(Collectors.groupingBy(Student::getType, Collectors.groupingBy(Student::getAge)));
 
//分区
//分成两部分,一部分大于10岁,一部分小于等于10岁
Map<Boolean, List<Student>> partMap = list.stream().collect(Collectors.partitioningBy(v -> v.getAge() > 10));
 
//规约
Integer allAge = list.stream().map(Student::getAge).collect(Collectors.reducing(Integer::sum)).get(); //40

4.Optional<T>

(1)概念

Optional 是一个对象容器,具有以下两个特点:

  • 提示用户要注意该对象有可能为null,同时可以防止nullpointer异常
  • 简化if else代码

(2)使用

①创建
Optional.empty(): 创建一个空的 Optional 实例

Optional.of(T t):创建一个 Optional 实例,当 t为null时抛出异常      

Optional.ofNullable(T t):创建一个 Optional 实例,但当 t为null时不会抛出异常,而是返回一个空的实例
②获取
get():获取optional实例中的对象,当optional 容器为空时报错

orElse(T other):如果optional不为空,则返回optional中的对象;如果为null,则返回 other 这个默认值

orElseGet(Supplier<T> other):如果optional不为空,则返回optional中的对象;如果为null,则使用Supplier函数生成默认值other

orElseThrow(Supplier<X> exception):如果optional不为空,则返回optional中的对象;如果为null,则抛出Supplier函数生成的异常
③判断
isPresent():判断optional是否为空,如果空则返回false,否则返回true
④过滤
filter(Predicate<T> p):如果optional不为空,则执行断言函数p。否则返回空的optional  
⑤映射
map(Function<T, U> mapper):如果optional不为空,则将optional中的对象 t 映射成另外一个对象 u,并将 u 存放到一个新的optional容器中。否则返回空的optional

flatMap(Function< T,Optional<U>> mapper):跟上面一样,在optional不为空的情况下,将对象t映射成另外一个optional。否则返回空的optional

Present():判断optional是否为空,如果空则返回false,否则返回true


#### ④过滤

filter(Predicate p):如果optional不为空,则执行断言函数p。否则返回空的optional


#### ⑤映射

    map(Function<T, U> mapper):如果optional不为空,则将optional中的对象 t 映射成另外一个对象 u,并将 u 存放到一个新的optional容器中。否则返回空的optional
    
    flatMap(Function< T,Optional<U>> mapper):跟上面一样,在optional不为空的情况下,将对象t映射成另外一个optional。否则返回空的optional
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值