JAVA新特性(3)stream的理解与使用

  1. 流:Stream由三部分构成:
    1)源
    2)零个或多个中间操作--惰性求值
    3)终止操作--及早求值
  2. 流的说明
    1 Collection提供了新的stream()方法
    2 流不存储值,通过管道的方式获取值
    3 本质是函数式的,对流的操作会生成一个结果,不过并不会修改底层的数据源,集合可以作为流的底层数据源
    4 延迟查找,很多流操作(过滤,映射,排序等)都可以延迟实现
        @Test
        public void TestStream(){
    //        创建流的几种方式
            Stream stream1 = Stream.of("we","we","wr","zhang");
    
            String[] arr = new String[]{"Hello","Hi","Good","Bad"};
            Stream stream2 = Arrays.stream(arr);
            Stream stream3 = Stream.of(arr);
    
            List<String> list = Arrays.asList("we","we","wr","zhang");
            Stream stream4 = list.stream();
        }
        @Test
        public void UseStream(){
            IntStream.of(new int[]{5,6,7}).forEach(System.out::println);//  5 6 7
            System.out.println("--------------");
            IntStream.range(3, 5).forEach(System.out::println);//3 4
            System.out.println("--------------");
            IntStream.rangeClosed(3, 5).forEach(System.out::println);//3 4 5
        }
    
        @Test
        public void OperatorStream(){
    //        实现:整型集合中所有元素相加再乘2得到结果
            List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9);
            System.out.println(list.stream().reduce(Integer::sum).map(i->i*2));
            System.out.println(list.stream().map(i->i*2).reduce(0,Integer::sum));
        }

     

  3. Stream的应用:
        @Test
        public void UseStream2() {
    //将流转化为数组对象
            Stream<String> stream1 = Stream.of("we", "we", "wr", "zhang");
    
    //        String[] strings = (String[])stream1.toArray();//方式一
    //        String[] strings = stream1.toArray(length->new String[length]);//方式二
            String[] strings = stream1.toArray(String[]::new);//方式三
            Arrays.asList(strings).forEach(System.out::println);
        }
    
        @Test
        public void UseStream3() {
    //        将流转化为不同的集合
            Stream<String> stream1 = Stream.of("we", "we", "wr", "zhang");
            Stream<String> stream2 = Stream.of("we", "we", "wr", "zhang");
            Stream<String> stream3 = Stream.of("we", "we", "wr", "zhang");
    
            List<String> list = stream1.collect(Collectors.toList());//方式一
    
            List<String> list2 = stream2.collect(()->new ArrayList<String>(),
                    (list1,item1)->list1.add(item1),(l1,l2)->l1.containsAll(l2));//方式二
    
            List<String> list3 = stream3.collect(LinkedList::new,LinkedList::add,LinkedList::addAll);//方式三
    
            list.forEach(System.out::println); //输出:we we wr zhang
            list2.forEach(System.out::println);//输出:we we wr zhang
            list3.forEach(System.out::println);//输出:we we wr zhang
        }
    
        @Test
        public void UseStream4() {
    //        将流转化为不同的集合,对流元素进行操作
            Stream<String> stream1 = Stream.of("we", "we", "wr", "zhang");
            Stream<String> stream2 = Stream.of("we", "we", "wr", "zhang");
            Stream<String> stream3 = Stream.of("we", "we", "wr", "zhang");
    
            Set<String> set = stream1.collect(Collectors.toCollection(TreeSet::new));//Set
            set.forEach(System.out::println);//输出:we  wr  zhang
    
            String str = stream2.collect(Collectors.joining());//连接元素为一个字符串操作
            System.out.println(str);//输出:wewrzhang
    
            //LinkedList并进行操作:
            List<String> list = stream3.collect(Collectors.toCollection(LinkedList::new));
            list.stream().map(String::toUpperCase).collect(Collectors.toList()).
                    forEach(System.out::println);//输出:WE WR ZHANG
    
            //flatMap的使用:得到 将流的每个元素按指定的函数操作后的所有元素形成的流
            Stream<List<Integer>> stream = Stream.of(Arrays.asList(1,2),
                    Arrays.asList(1),Arrays.asList(8,9,10));
            stream.flatMap(list1 -> list1.stream()).map(i->i*i).forEach(System.out::println);
        }

    进阶:

        @Test
        public void Test(){
            Stream<String> stream = Stream.generate(UUID.randomUUID()::toString);
            stream.findFirst().ifPresent(System.out::println);
            //findFirst返回流的第一个元素,且类型为Optional
    
            Stream.iterate(1, i->i+2).limit(5).forEach(System.out::println);
            //输出:1 3 5 7 9
    
            System.out.println("------------------------");
            //找出其中大于2的元素,然后将每个元素乘以2,然后忽略掉元素中的前两个元素,
            // 再取流中的前两个元素,再求总和/最小值
            Stream<Integer> stream1 = Stream.iterate(1, i->i+2).limit(5);
            Stream<Integer> stream2 = Stream.iterate(1, i->i+2).limit(5);
            Stream<Integer> stream3 = Stream.iterate(1, i->i+2).limit(5);
    
    //        stream1.filter(i->i>2).map(i->i*2).skip(2).limit(2).reduce(Integer::sum);
    //        System.out.println(stream1.filter(i->i>2).map(i->i*2).skip(2).limit(2).reduce(Integer::sum));
            System.out.println(stream1.filter(i->i>2).mapToInt(i->i*2).skip(2).limit(2).sum());//32 无则为0
    
            System.out.println("------------------------");
    //        System.out.println(stream1.filter(i->i>200).mapToInt(i->i*2).skip(2).limit(2).min());
            stream2.filter(i->i>2).mapToInt(i->i*2).skip(2).limit(2).min().
                    ifPresent(System.out::println);//14
    
            System.out.println("------------------------");
            IntSummaryStatistics intSummaryStatistics =
             stream3.filter(i->i>2).mapToInt(i->i*2).skip(2).limit(2).summaryStatistics();
            System.out.println(intSummaryStatistics.getMax());//18
            System.out.println(intSummaryStatistics.getAverage());//16.0
            System.out.println(intSummaryStatistics.getMin());//14
        }

     

  4. 对已经进行操作过的流对象不能再进行操作,可以对新创建的流对象进行操作
    有终止操作,才对流开始计算操作
        @Test
        public void TestRepeat(){
            Stream<Integer> stream = Stream.iterate(1, i->i+2).limit(5);//创建新的流
            System.out.println(stream);
            Stream<Integer> stream1 = stream.filter(i->i>2);//对流操作,创建新的流
            System.out.println(stream1);
            //对已操作过的流stream不能直接进行操作,对新的流对象stream1进行操作
            Stream<Integer> stream2 = stream1.distinct();
            System.out.println(stream2);
        }
    
        @Test
        public void TestRepeat2(){
            List<String> list = Arrays.asList("hello","word","hello world");
            List<String> list1 = Arrays.asList("hello","word","hello world");
    
            list.stream().map(i->i.substring(0,1).toUpperCase() + i.substring(1)).forEach(System.out::println);
    
            System.out.println("----------------");
            Stream<String> stringStream = list1.stream().map(i-> {
                String result = i.substring(0,1).toUpperCase() + i.substring(1);
                System.out.println("test");
                return result;
            });//中间操作,需要有终止操作才能倒着完成中间的操作
    //        stringStream.forEach(System.out::println);
    
            System.out.println("----------------");
            IntStream.iterate(0, i->(i+1)%2).limit(6).distinct().forEach(System.out::println);//正常
    //        IntStream.iterate(0, i->(i+1)%2).distinct().limit(6).forEach(System.out::println);//不停的运行
        }
  5. 外部迭代与内部迭代(图片源自网络)

  6. 代码示例:
            @Test
        public void TestParallel(){
            List<String> list = new ArrayList<>(5000000);
            for(int i=0;i<5000000;i++){
                list.add(UUID.randomUUID().toString());
            }
            System.out.println("开始排序");
            long starttime = System.nanoTime();
            list.stream().sorted().count();
            long endtime = System.nanoTime();
            long millis = TimeUnit.NANOSECONDS.toMillis(endtime-starttime);
            System.out.println("排序耗时:" + millis);
    
            System.out.println("开始排序");
            starttime = System.nanoTime();
            list.parallelStream().sorted().count();//并行
            endtime = System.nanoTime();
            millis = TimeUnit.NANOSECONDS.toMillis(endtime-starttime);
            System.out.println("排序耗时:" + millis);
        }
        @Test
        public void TestPrinciple(){
    //      对流进行操作,一个操作容器,并对操作串行化,即对流的每个元素进行短路操作
    //      实现:输出集合中第一个长度为5的字符串
            List<String> list = Arrays.asList("Hello1","world","Liu LIU");
            list.stream().mapToInt(i->{
                int length = i.length();
                System.out.println(i);
                return length;
            }).filter(i->i == 5).
                    findFirst().ifPresent(System.out::println);//输出: Hello  5
        }
    
        @Test
        public void Test(){
    //        实现:得到将集合中所有元素且无重复
            List<String> list = Arrays.asList("Hello","Hello world",
                    "welcome the Hello world","Hello welcome");
    
            list.stream().map(item -> item.split(" ")).distinct().
                    collect(Collectors.toList()).forEach(System.out::println);
            //不可取,返回四个String[]
    
            //需要使用flatMap:distinct去重或用Set(无重复元素)
            List<String> result = list.stream().map(item -> item.split(" ")).
                    flatMap(Arrays::stream).distinct().collect(Collectors.toList());
            Set<String> strings = list.stream().map(item -> item.split(" ")).
                    flatMap(Arrays::stream).collect(Collectors.toCollection(TreeSet::new));
    
            result.stream().forEach(System.out::println);//输出:Hello world welcome the
            System.out.println("-----------------------");
            strings.stream().forEach(System.out::println);//输出:Hello world welcome the
        }
    
        @Test
        public void Test1(){
    //        实现:list1+list2 交叉叠加输出(不同放式和不同人打招呼)
            List<String> list1 = Arrays.asList("Hello","Hi");
            List<String> list2 = Arrays.asList("zhong hua","tian men","liu jia");
            List<String> stringList = list1.stream().flatMap(i->list2.stream().
                    map(i2->i + " " + i2)).collect(Collectors.toList());
            stringList.forEach(System.out::println);
        }
     
    概念理解:

    集合关注的是数据与数据存储本身
    关注的这是对数据的计算
    流与迭代器类似的一点是:流是无法重复使用或消费的
    中间操作都会返回一个Stream对象
    终止操作则不会返回Stream类型,可能不返回值,也可能返回其他类型的单个值
    流的短路:对流进行操作时,对每个元素进行操作容器里的操作;很多个操作,但对流中元素只进行了一次迭代。
     
  7. 流中的分组(与SQL语句非常像)、分区(只有两组):
    图片来自网络
    public class StreamGroupingTest {
        @Test
        public void TestGrouping(){
    //        分组与分区功能的实现(可与SQL语句对比)
            SomePerson somePerson1 = new SomePerson("liuliu", 21,100 );
            SomePerson somePerson2 = new SomePerson("tian", 11,100 );
            SomePerson somePerson3 = new SomePerson("men", 11,100 );
            SomePerson somePerson4 = new SomePerson("tian", 30,110 );
    
            List<SomePerson> somes = Arrays.asList(somePerson1,somePerson2,somePerson3,somePerson4);
            //按姓名分
            Map<String,List<SomePerson>> mapName = somes.stream().
                    collect(Collectors.groupingBy(SomePerson::getName));
            //按高度分
            Map<Integer,List<SomePerson>> mapHeigt = somes.stream().
                    collect(Collectors.groupingBy(SomePerson::getHeight));
            //按高度分,且统计个数
            Map<Integer,Long> mapAndCount = somes.stream().
                    collect(Collectors.groupingBy(SomePerson::getHeight, Collectors.counting()));
            //按姓名分,且统计高度相关信息
            Map<String,Double> mapNameAndCompute = somes.stream().collect(Collectors.
                    groupingBy(SomePerson::getName, Collectors.averagingInt(SomePerson::getHeight)));
            //分区
            Map<Boolean,List<SomePerson>> mapTwo = somes.stream().collect(Collectors.
                    partitioningBy(s->s.getAge() >= 20));
    
            System.out.println(mapName);
            System.out.println(mapHeigt);
            System.out.println(mapAndCount);//输出: {100=3, 110=1}
            System.out.println(mapNameAndCompute);//输出:{tian=105.0, men=100.0, liuliu=100.0}
            System.out.println(mapTwo);
            mapTwo.get(true).forEach(i-> System.out.println(i.getAge()));//输出:21 30
        }
    }
    class SomePerson{
        private String name;
        private int age;
        private int height;
    
        public SomePerson(String name, int age, int height) {
            this.name = name;
            this.age = age;
            this.height = height;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public int getHeight() {
            return height;
        }
    
        public void setHeight(int height) {
            this.height = height;
        }
    }








     
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 好的,我来帮助你使用 Java 8 的新特性来优化这段代码。 首先,我们可以使用 Java 8 中的 Stream API 和 Lambda 表达式来优化这段代码。 使用 Stream API 和 Lambda 表达式可以帮助我们简化代码,并提高代码的可读性。 例如,我们可以使用 Stream API 来代替 for 循环,并使用 Lambda 表达式来简化 if 语句。 例如,下面是使用 Stream API 和 Lambda 表达式优化后的代码: ``` List<String> result = list.stream() .filter(s -> s.length() > 3) .map(String::toUpperCase) .collect(Collectors.toList()); ``` 另外,我们还可以使用 Java 8 中的 Optional 类来优化这段代码。Optional 类是一个可以为 null 的容器对象,它可以帮助我们避免空指针异常。 例如,我们可以使用 Optional 类来代替 if 语句,从而使代码更加简洁。 例如,下面是使用 Optional 类优化后的代码: ``` Optional<String> result = list.stream() .filter(s -> s.length() > 3) .map(String::toUpperCase) .findFirst(); ``` 希望这些建议能帮助你使用 Java 8 的新特性优化代码。 ### 回答2: 使用Java 8的新特性可以优化这段代码。有几个可以改进的方面: 1. 使用Lambda表达式来替代匿名内部类:Lambda表达式可以简化代码,提高可读性。比如,在使用线程时可以使用Lambda表达式来创建匿名线程。 2. 使用流操作来替代循环:Java 8引入了Stream API,可以通过流操作来处理集合数据,简化了循环的使用。在处理集合数据时,可以使用流操作来替代传统的循环。 3. 使用Optional类来避免NullPointerException:Optional类是Java 8中引入的用于解决NullPointerException的问题。可以使用Optional类来替代传统的空指针检查,提高代码的健壮性。 4. 使用新的日期和时间API:Java 8引入了新的日期和时间API,提供了一种更加简单和方便的方式来处理日期和时间。可以使用新的日期和时间API来替代旧的Date和Calendar类,使代码更加清晰和易于维护。 通过使用Java8的新特性,能够简化代码,提高可读性和性能。这些优化将使代码更加清晰,易于理解和维护。 ### 回答3: 使用Java 8的新特性可以通过Lambda表达式和流(stream)来优化代码。考虑以下示例代码: ```java List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David"); // 原始代码 List<String> result = new ArrayList<>(); for (String name : names) { if (name.startsWith("A")) { result.add(name.toUpperCase()); } } ``` 我们可以使用Java 8提供的Lambda表达式和流来优化上面的代码,使其更加简洁和易读。 ```java List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David"); // 使用Lambda表达式和流优化后的代码 List<String> result = names.stream() .filter(name -> name.startsWith("A")) .map(String::toUpperCase) .collect(Collectors.toList()); ``` 通过使用`stream()`方法将集合转换为流,我们可以使用`filter()`方法过滤出以"A"开头的姓名,然后使用`map()`方法将名称转换为大写,最后使用`collect()`方法将结果收集到一个新的列表中。 这样的优化代码不但更简洁,同时也更易于理解和维护。Lambda表达式和流的引入使代码更加函数式和声明式,减少了冗余代码。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值