目 录CONTENT

文章目录

JDK1.8 实用新特性 Stream

小张的探险日记
2021-12-20 / 0 评论 / 0 点赞 / 633 阅读 / 6,845 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2021-12-20,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

什么是 Stream

9a8e3b4f0d1e3a72a8b423f02adceffc_4d086e061d950a7b4dede69893f2fedcf3d3c9bf_token=8fa23caae2dd679b8837d09878bf72f2s=B903A05E82F0AC6B5AFE54130200F0CB.jpeg

Jdk1.8 为了强化对集合的操作,新增了Stream 特性,使开发者对集合的操作更加简便,快速!Stream 是提供了 元素流上的功能样式操作的类

例如集合上的map-reduce转换。例如:

int sum = widgets.stream()
                      .filter(b -> b.getColor() == RED)
                      .mapToInt(b -> b.getWeight())
                      .sum();

Stream 的特性

流在几个方面与集合不同:

  1. 没有存储空间。流不是存储元素的数据结构。相反,它通过一系列计算操作从数据结构,数组,生成器功能或I / O通道等源中传递元素。

  2. 本质上是功能性的。对流的操作会产生结果,但不会修改其源。例如,对Stream 从集合中获取的a Stream进行过滤会产生一个不包含过滤后元素的新元素,而不是从源集合中删除元素。

  3. 懒惰寻求。许多流操作(例如过滤,映射或重复删除)可以延迟实施,从而暴露出进行优化的机会。

  4. 可能无界。尽管集合的大小是有限的,但流不是必需的。诸如limit(n)或 的短路操作findFirst()可以允许对无限流的计算在有限时间内完成。

  5. 消耗品。在流的生存期内,流的元素只能访问一次。与一样Iterator,必须生成新的流以重新访问源中的相同元素。

流可以通过多种方式获得。一些示例包括:

从Collection通过stream()与 parallelStream()方法;

从数组通过Arrays.stream(Object[]);

从上流类静态工厂方法,例如 Stream.of(Object[]), IntStream.range(int, int) 或Stream.iterate(Object, UnaryOperator);

文件的行可以从以下位置获得BufferedReader.lines():

可以从中的方法获得文件路径流Files。

可以从中获得随机数流Random.ints();

在JDK许多其他流的轴承的方法,包括 BitSet.stream(), Pattern.splitAsStream(java.lang.CharSequence),和JarFile.stream()。

Stream 相关用法案例:

/**
 *  获取第一个值
 *  如果 stream 没有顺序 那么都有可能返回
 *  如果所选元素 为 空  那么 抛出 NullPointException
 */
public static void getFirstValue(){
    List<Integer> list1 = getList();
    Optional<Integer> first = list1.stream().findFirst();
    System.out.println(first);
}


/**
 *  去重复
 */
public static void distinctTest(){
    List<Integer> list = getList();
    List<Integer> list1 = list.stream().distinct().collect(toList());
    System.out.println(list1);
}


/**
 *  获取任意 元素
 *  如果流为空,则为空
 */
public static void findAnyTest(){
    List<Integer> list1 = getList();
    Optional<Integer> any = list1.stream().findAny();
    System.out.println(any);
}


/**
 *  过滤器
 */
public static void filterTest(){
    List<Integer> list1 = getList();
    List list = list1.stream().filter(str->{
        if(1 == str||2 == str){
            return true;
        }
        return false;
    }).collect(toList());
    System.out.println(list);
}


/**
 *  元素加工处理
 *
 */
public static void mapTest(){
    List<Integer> list1 = getList();
    List<Integer> collect = list1.stream().map(str -> str + 1).collect(toList());
    System.out.println(collect);
}

/**
 *  相对 Map 更深层次
 */
public static void flatMapTest(){
    List<Person> personList = getPeopleList();
    // 深层次的循环
    // flatMap可以操作对象里面的对象,而map只能操作第一层。
    // 如果入参的是对象,那么 flatMap 可以操作到对象的属性,而map 只能操作到 对象
    // 及早求值
    List resultList1 = personList.stream()
            .flatMap(person -> Arrays.stream(person.getName().split(" "))).collect(toList());
    //打印姓名
    System.out.println(resultList1);
    // 对比 map  惰性求值
    List<Stream<String>> resultList2 = personList.stream()
            .map(person -> Arrays.stream(person.getName().split(" "))).collect(toList());
    // 打印 Stream 对象 地址
    System.out.println(resultList2);
}


/**
 *  累加测试
 */
public static void reduceTest(){
    List<Integer> arr = getList();
    // 累加
    Integer reduce1 = arr.stream().reduce(10, (sun, item) -> {
        return sun + item;
    });
    //简写
    Integer reduce2 = arr.stream().reduce(10, (sun, item) ->sun + item);
    // 字符串累加 拼接
    String reduce3 = Stream.of("1", "2", "3")
            .reduce("0", (x, y) -> (x + "," + y));
    System.out.println(reduce2);
    // 打印 17
    System.out.println(reduce1);
    System.out.println(reduce2);
    System.out.println(reduce3);
}

/**
 *  以下演示 Collect 的相关用法
 *
 * 1 toList()
 *
 * 2、toSet()
 *
 * 3、toMap()
 *
 * 4、自定义
 */
public static void toListTest(){
    List<Double> collect = getList().stream().map(Integer::doubleValue).collect(toList());
    //打印 [1.0, 3.0, 1.0, 2.0]
    System.out.println(collect);
}
public static void toSetTest(){
    Set<Double> collect = getList().stream().map(Integer::doubleValue).collect(toSet());
    //打印 [1.0, 2.0, 3.0]   自动去重复
    System.out.println(collect);
}
public static void toMapTest(){
    List<Person> personList = getPeopleList();
    Map<String, Integer> collect = personList.stream().collect(toMap(Person::getName, Person::getAge));
    //打印 {zhang2=3, zhang3=4, zhang0=1, zhang1=2, zhang8=9, zhang9=10, zhang6=7, zhang7=8, zhang4=5, zhang5=6}   乱序
    System.out.println(collect);
}


/**
 * 转换成 指定类型
 */
public static void toTreeSetTest(){
    List<Integer> list = getList();
    TreeSet collect = list.stream()
            .collect(Collectors.toCollection(TreeSet::new));
    System.out.println(collect);
}


/**
 * 分组
 */
public static void toGroupTest(){
    List<Person> data = getPeopleList();
    Map<Boolean, List<Person>> collect = data.stream()
            .collect(Collectors.groupingBy(person -> person.getAge()>5));
    Iterator<Map.Entry<Boolean, List<Person>>> iterator = collect.entrySet().iterator();
    while(iterator.hasNext()){
        Map.Entry<Boolean, List<Person>> next = iterator.next();
        List<Person> personList = next.getValue();
        if(next.getKey() == true){
            personList.forEach(person->System.out.println(Strings.lenientFormat("年龄 5岁以上的-姓名: %s",person.getName())));
        }else{
            personList.forEach(person->System.out.println(Strings.lenientFormat("年龄 5岁以下的-姓名: %s",person.getName())));
        }
    }
}


/**
 * 分隔
 */
public static void toJoiningTest(){
    List<Person> peopleList = getPeopleList();
    String collect = peopleList.stream()
            .map(person -> person.getName())
            //以 , 分割 前后缀分别为 {  }
            .collect(Collectors.joining(",", "{", "}"));
    System.out.println(collect);
}


/**
 *  累加
 */
public static void toReduceTest(){
    List collect = Stream.of("1", "2", "3","4").collect(
            Collectors.reducing(new ArrayList(), x -> Arrays.asList(x), (y, z) -> {
                y.addAll(z);
                return y;
            }));
    System.out.println(collect);
}


/**
 *  并发

 */
public static void paralleList(){
    int size = 10;
    List<Integer> list = new ArrayList<>(size);
    for (Integer i = 0; i < size; i++) {
        list.add(new Integer(i));
    }
    List<Integer> temp1 = new ArrayList<>(size);
    //老的
    long start=System.currentTimeMillis();
    for (Integer i: list) {
        temp1.add(i);
    }
    System.out.println(+System.currentTimeMillis()-start);
    //同步
    long start1=System.currentTimeMillis();
    list.stream().collect(Collectors.toList());
    System.out.println(System.currentTimeMillis()-start1);
    //并发
    long start2=System.currentTimeMillis();
    list.parallelStream().collect(Collectors.toList());
    System.out.println(System.currentTimeMillis()-start2);
}


/**
     *  线程安全问题

        线程不安全问题,

            1.可以使用 Lock,Synchronize等锁机制 使线程安全

            2.使用线程安全的集合类 如 CopyOnWriteArrayList,ConcurrentHashMap



     */
    public static void paralleSafety(){
        List<Integer> list1 = new ArrayList<Integer>();
        List<Integer> list2 = new ArrayList<Integer>();
        List<Integer> list3 = new ArrayList<Integer>();
        List<Integer> list4 = new CopyOnWriteArrayList<Integer>();
        long millis = System.currentTimeMillis();
        IntStream.range(0,1000).forEach(list1::add);
        long endMillis = System.currentTimeMillis();
//        System.out.println(endMillis-millis);
        //线程不安全
//        IntStream.range(0,1000).parallel().forEach(list2::add);
        IntStream.range(0,1000).parallel().forEach(list4::add);
        long millis1 = System.currentTimeMillis();
        Lock lock = new ReentrantLock();
        IntStream.range(0, 1000).parallel().forEach(i -> {
            lock.lock();
            try {
                list3.add(i);
            }finally {
                lock.unlock();
            }
        });
        long endMillis1 = System.currentTimeMillis();
//        System.out.println(endMillis1-millis1);
        System.out.println(list1.size());
        System.out.println(list2.size());
        System.out.println(list3.size());
        System.out.println(list4.size());
    }


/**
 *  调试
 *  .
 *  使用 peek 打印值
 */
public static void debugTest(){
    List<Integer> list = getList();
    List<Long> collect = list.stream().map(value -> value.longValue()).peek(v -> {
        System.out.println(v == 10);
    }).collect(toList());
    System.out.println(collect);
}
0

评论区