Java8新特性有哪些亮点?

2026-05-26 01:421阅读0评论SEO资讯
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计2422个文字,预计阅读时间需要10分钟。

Java8新特性有哪些亮点?

目录 + Stream结果收集 + 结果收集到集合中 + 结果收集到数组中 + 对流中的数据进行聚合计算 + 对流中的数据进行分组操作 + 对流中的数据进行分区操作 + 对流中的数据进行拼接 + 并行的Stream流 + 串行的Stream流

目录
  • Stream结果收集
    • 结果收集到集合中
    • 结果收集到数组中
    • 对流中的数据做聚合计算
    • 对流中数据做分组操作
    • 对流中的数据做分区操作
    • 对流中的数据做拼接
  • 并行的Stream流
    • 串行的Stream流
    • 并行流
      • 获取并行流
      • 并行流操作
    • 并行流和串行流对比
      • 线程安全问题

      Stream结果收集

      面试官:说说你常用的StreamAPI。

      结果收集到集合中

      public static void main(String[] args){ // Stream<String> stream = Stream.of("aa", "bb", "cc"); List<String> list = Stream.of("aa", "bb", "cc","aa") .collect(Collectors.toList()); System.out.println(list); // 收集到 Set集合中 Set<String> set = Stream.of("aa", "bb", "cc", "aa") .collect(Collectors.toSet()); System.out.println(set); // 如果需要获取的类型为具体的实现,比如:ArrayList HashSet ArrayList<String> arrayList = Stream.of("aa", "bb", "cc", "aa") //.collect(Collectors.toCollection(() -> new ArrayList<>())); .collect(Collectors.toCollection(ArrayList::new)); System.out.println(arrayList); HashSet<String> hashSet = Stream.of("aa", "bb", "cc", "aa") .collect(Collectors.toCollection(HashSet::new)); System.out.println(hashSet); }

      输出:

      [aa, bb, cc, aa]
      [aa, bb, cc]
      [aa, bb, cc, aa]
      [aa, bb, cc]

      结果收集到数组中

      Stream中提供了toArray方法来将结果放到一个数组中,返回值类型是Object[],如果我们要指定返回的类型,那么可以使用另一个重载的toArray(IntFunction f)方法。

      public static void main(String[] args){ Object[] objects = Stream.of("aa", "bb", "cc", "aa") .toArray(); // 返回的数组中的元素是 Object类型 System.out.println(Arrays.toString(objects)); // 如果我们需要指定返回的数组中的元素类型 String[] strings = Stream.of("aa", "bb", "cc", "aa") .toArray(String[]::new); System.out.println(Arrays.toString(strings)); }

      对流中的数据做聚合计算

      当我们使用Stream流处理数据后,可以像数据库的聚合函数一样对某个字段进行操作,比如获得最大值,最小值,求和,平均值,统计数量。

      public static void main(String[] args) { // 获取年龄的最大值 Optional<Person> maxAge = Stream.of( new Person("张三", 18) , new Person("李四", 22) , new Person("张三", 13) , new Person("王五", 15) , new Person("张三", 19) ).collect(Collectors.maxBy((p1, p2) -> p1.getAge() - p2.getAge())); System.out.println("最大年龄:" + maxAge.get()); // 获取年龄的最小值 Optional<Person> minAge = Stream.of( new Person("张三", 18) , new Person("李四", 22) , new Person("张三", 13) , new Person("王五", 15) , new Person("张三", 19) ).collect(Collectors.minBy((p1, p2) -> p1.getAge() - p2.getAge())); System.out.println("最新年龄:" + minAge.get()); // 求所有人的年龄之和 Integer sumAge = Stream.of( new Person("张三", 18) , new Person("李四", 22) , new Person("张三", 13) , new Person("王五", 15) , new Person("张三", 19) ) //.collect(Collectors.summingInt(s -> s.getAge())) .collect(Collectors.summingInt(Person::getAge)) ; System.out.println("年龄总和:" + sumAge); // 年龄的平均值 Double avgAge = Stream.of( new Person("张三", 18) , new Person("李四", 22) , new Person("张三", 13) , new Person("王五", 15) , new Person("张三", 19) ).collect(Collectors.averagingInt(Person::getAge)); System.out.println("年龄的平均值:" + avgAge); // 统计数量 Long count = Stream.of( new Person("张三", 18) , new Person("李四", 22) , new Person("张三", 13) , new Person("王五", 15) , new Person("张三", 19) ).filter(p->p.getAge() > 18) .collect(Collectors.counting()); System.out.println("满足条件的记录数:" + count); }

      对流中数据做分组操作

      当我们使用Stream流处理数据后,可以根据某个属性将数据分组。

      public static void main(String[] args){ // 根据账号对数据进行分组 Map<String, List<Person>> map1 = Stream.of( new Person("张三", 18, 175) , new Person("李四", 22, 177) , new Person("张三", 14, 165) , new Person("李四", 15, 166) , new Person("张三", 19, 182) ).collect(Collectors.groupingBy(Person::getName)); map1.forEach((k,v)-> System.out.println("k=" + k +"\t"+ "v=" + v)); System.out.println("-----------"); // 根据年龄分组 如果大于等于18 成年否则未成年 Map<String, List<Person>> map2 = Stream.of( new Person("张三", 18, 175) , new Person("李四", 22, 177) , new Person("张三", 14, 165) , new Person("李四", 15, 166) , new Person("张三", 19, 182) ).collect(Collectors.groupingBy(p -> p.getAge() >= 18 ? "成年" : "未成年")); map2.forEach((k,v)-> System.out.println("k=" + k +"\t"+ "v=" + v)); }

      输出结果:

      k=李四 v=[Person{name='李四', age=22, height=177}, Person{name='李四', age=15, height=166}]
      k=张三 v=[Person{name='张三', age=18, height=175}, Person{name='张三', age=14, height=165}, Person{name='张三', age=19, height=182}]
      -----------
      k=未成年 v=[Person{name='张三', age=14, height=165}, Person{name='李四', age=15, height=166}]
      k=成年 v=[Person{name='张三', age=18, height=175}, Person{name='李四', age=22, height=177}, Person{name='张三', age=19, height=182}]

      多级分组: 先根据name分组然后根据年龄分组。

      public static void main(String[] args){ // 先根据name分组,然后根据age(成年和未成年)分组 Map<String,Map<Object,List<Person>>> map = Stream.of( new Person("张三", 18, 175) , new Person("李四", 22, 177) , new Person("张三", 14, 165) , new Person("李四", 15, 166) , new Person("张三", 19, 182) ).collect(Collectors.groupingBy( Person::getName ,Collectors.groupingBy(p->p.getAge()>=18?"成年":"未成年" ) )); map.forEach((k,v)->{ System.out.println(k); v.forEach((k1,v1)->{ System.out.println("\t"+k1 + "=" + v1); }); }); }

      输出结果:

      李四
      未成年=[Person{name='李四', age=15, height=166}]
      成年=[Person{name='李四', age=22, height=177}]
      张三
      未成年=[Person{name='张三', age=14, height=165}]
      成年=[Person{name='张三', age=18, height=175}, Person{name='张三', age=19, height=182}]

      对流中的数据做分区操作

      Collectors.partitioningBy会根据值是否为true,把集合中的数据分割为两个列表,一个true列表,一个false列表。

      public static void main(String[] args){ Map<Boolean, List<Person>> map = Stream.of( new Person("张三", 18, 175) , new Person("李四", 22, 177) , new Person("张三", 14, 165) , new Person("李四", 15, 166) , new Person("张三", 19, 182) ).collect(Collectors.partitioningBy(p -> p.getAge() > 18)); map.forEach((k,v)-> System.out.println(k+"\t" + v)); }

      输出结果:

      false [Person{name='张三', age=18, height=175}, Person{name='张三', age=14, height=165}, Person{name='李四', age=15, height=166}]
      true [Person{name='李四', age=22, height=177}, Person{name='张三', age=19, height=182}]

      对流中的数据做拼接

      Collectors.joining会根据指定的连接符,将所有的元素连接成一个字符串。

      public static void main(String[] args){ String s1 = Stream.of( new Person("张三", 18, 175) , new Person("李四", 22, 177) , new Person("张三", 14, 165) , new Person("李四", 15, 166) , new Person("张三", 19, 182) ).map(Person::getName) .collect(Collectors.joining()); // 张三李四张三李四张三 System.out.println(s1); String s2 = Stream.of( new Person("张三", 18, 175) , new Person("李四", 22, 177) , new Person("张三", 14, 165) , new Person("李四", 15, 166) , new Person("张三", 19, 182) ).map(Person::getName) .collect(Collectors.joining("_")); // 张三_李四_张三_李四_张三 System.out.println(s2); String s3 = Stream.of( new Person("张三", 18, 175) , new Person("李四", 22, 177) , new Person("张三", 14, 165) , new Person("李四", 15, 166) , new Person("张三", 19, 182) ).map(Person::getName) .collect(Collectors.joining("_", "###", "$$$")); // ###张三_李四_张三_李四_张三$$$ System.out.println(s3); }

      并行的Stream流

      Java8新特性有哪些亮点?

      串行的Stream流

      我们前面使用的Stream流都是串行,也就是在一个线程上面执行。

      并行流

      parallelStream其实就是一个并行执行的流,它通过默认的ForkJoinPool,可以提高多线程任务的速度。

      获取并行流

      我们可以通过两种方式来获取并行流。

      • 通过List接口中的parallelStream方法来获取
      • 通过已有的串行流转换为并行流(parallel)

      public static void main(String[] args){ List<Integer> list = new ArrayList<>(); // 通过List 接口 直接获取并行流 Stream<Integer> integerStream = list.parallelStream(); // 将已有的串行流转换为并行流 Stream<Integer> parallel = Stream.of(1, 2, 3).parallel(); }

      并行流操作

      public static void main(String[] args){ Stream.of(1,4,2,6,1,5,9) .parallel() // 将流转换为并发流,Stream处理的时候就会通过多线程处理 .filter(s->{ System.out.println(Thread.currentThread() + " s=" +s); return s > 2; }).count(); }

      并行流和串行流对比

      我们通过for循环,串行Stream流,并行Stream流来对500000000亿个数字求和。来看消耗时间。

      public class Test { private static long times = 500000000; private long start; @Before public void befor(){ start = System.currentTimeMillis(); } @After public void end(){ long end = System.currentTimeMillis(); System.out.println("消耗时间:" + (end - start)); } /** * 普通for循环 消耗时间:138 */ @Test public void test01(){ System.out.println("普通for循环:"); long res = 0; for (int i = 0; i < times; i++) { res += i; } } /** * 串行流处理 * 消耗时间:203 */ @Test public void test02(){ System.out.println("串行流:serialStream"); LongStream.rangeClosed(0,times) .reduce(0,Long::sum); } /** * 并行流处理 消耗时间:84 */ @Test public void test03(){ LongStream.rangeClosed(0,times) .parallel() .reduce(0,Long::sum); } }

      通过案例我们可以看到parallelStream的效率是最高的。

      Stream并行处理的过程会分而治之,也就是将一个大的任务切分成了多个小任务,这表示每个任务都是一个线程操作。

      线程安全问题

      在多线程的处理下,肯定会出现数据安全问题。如下:

      @Test public void test(){ List<Integer> list = new ArrayList<>(); for (int i = 0; i < 1000; i++) { list.add(i); } System.out.println(list.size()); List<Integer> listNew = new ArrayList<>(); // 使用并行流来向集合中添加数据 list.parallelStream() //.forEach(s->listNew.add(s)); .forEach(listNew::add); System.out.println(listNew.size());// 839 }

      针对这个问题,我们的解决方案有哪些呢?

      • 加同步锁
      • 使用线程安全的容器
      • 通过Stream中的toArray/collect操作

      以上就是Java8新特性 StreamAPI实例详解的详细内容,更多关于Java8新特性 StreamAPI的资料请关注自由互联其它相关文章!

      本文共计2422个文字,预计阅读时间需要10分钟。

      Java8新特性有哪些亮点?

      目录 + Stream结果收集 + 结果收集到集合中 + 结果收集到数组中 + 对流中的数据进行聚合计算 + 对流中的数据进行分组操作 + 对流中的数据进行分区操作 + 对流中的数据进行拼接 + 并行的Stream流 + 串行的Stream流

      目录
      • Stream结果收集
        • 结果收集到集合中
        • 结果收集到数组中
        • 对流中的数据做聚合计算
        • 对流中数据做分组操作
        • 对流中的数据做分区操作
        • 对流中的数据做拼接
      • 并行的Stream流
        • 串行的Stream流
        • 并行流
          • 获取并行流
          • 并行流操作
        • 并行流和串行流对比
          • 线程安全问题

          Stream结果收集

          面试官:说说你常用的StreamAPI。

          结果收集到集合中

          public static void main(String[] args){ // Stream<String> stream = Stream.of("aa", "bb", "cc"); List<String> list = Stream.of("aa", "bb", "cc","aa") .collect(Collectors.toList()); System.out.println(list); // 收集到 Set集合中 Set<String> set = Stream.of("aa", "bb", "cc", "aa") .collect(Collectors.toSet()); System.out.println(set); // 如果需要获取的类型为具体的实现,比如:ArrayList HashSet ArrayList<String> arrayList = Stream.of("aa", "bb", "cc", "aa") //.collect(Collectors.toCollection(() -> new ArrayList<>())); .collect(Collectors.toCollection(ArrayList::new)); System.out.println(arrayList); HashSet<String> hashSet = Stream.of("aa", "bb", "cc", "aa") .collect(Collectors.toCollection(HashSet::new)); System.out.println(hashSet); }

          输出:

          [aa, bb, cc, aa]
          [aa, bb, cc]
          [aa, bb, cc, aa]
          [aa, bb, cc]

          结果收集到数组中

          Stream中提供了toArray方法来将结果放到一个数组中,返回值类型是Object[],如果我们要指定返回的类型,那么可以使用另一个重载的toArray(IntFunction f)方法。

          public static void main(String[] args){ Object[] objects = Stream.of("aa", "bb", "cc", "aa") .toArray(); // 返回的数组中的元素是 Object类型 System.out.println(Arrays.toString(objects)); // 如果我们需要指定返回的数组中的元素类型 String[] strings = Stream.of("aa", "bb", "cc", "aa") .toArray(String[]::new); System.out.println(Arrays.toString(strings)); }

          对流中的数据做聚合计算

          当我们使用Stream流处理数据后,可以像数据库的聚合函数一样对某个字段进行操作,比如获得最大值,最小值,求和,平均值,统计数量。

          public static void main(String[] args) { // 获取年龄的最大值 Optional<Person> maxAge = Stream.of( new Person("张三", 18) , new Person("李四", 22) , new Person("张三", 13) , new Person("王五", 15) , new Person("张三", 19) ).collect(Collectors.maxBy((p1, p2) -> p1.getAge() - p2.getAge())); System.out.println("最大年龄:" + maxAge.get()); // 获取年龄的最小值 Optional<Person> minAge = Stream.of( new Person("张三", 18) , new Person("李四", 22) , new Person("张三", 13) , new Person("王五", 15) , new Person("张三", 19) ).collect(Collectors.minBy((p1, p2) -> p1.getAge() - p2.getAge())); System.out.println("最新年龄:" + minAge.get()); // 求所有人的年龄之和 Integer sumAge = Stream.of( new Person("张三", 18) , new Person("李四", 22) , new Person("张三", 13) , new Person("王五", 15) , new Person("张三", 19) ) //.collect(Collectors.summingInt(s -> s.getAge())) .collect(Collectors.summingInt(Person::getAge)) ; System.out.println("年龄总和:" + sumAge); // 年龄的平均值 Double avgAge = Stream.of( new Person("张三", 18) , new Person("李四", 22) , new Person("张三", 13) , new Person("王五", 15) , new Person("张三", 19) ).collect(Collectors.averagingInt(Person::getAge)); System.out.println("年龄的平均值:" + avgAge); // 统计数量 Long count = Stream.of( new Person("张三", 18) , new Person("李四", 22) , new Person("张三", 13) , new Person("王五", 15) , new Person("张三", 19) ).filter(p->p.getAge() > 18) .collect(Collectors.counting()); System.out.println("满足条件的记录数:" + count); }

          对流中数据做分组操作

          当我们使用Stream流处理数据后,可以根据某个属性将数据分组。

          public static void main(String[] args){ // 根据账号对数据进行分组 Map<String, List<Person>> map1 = Stream.of( new Person("张三", 18, 175) , new Person("李四", 22, 177) , new Person("张三", 14, 165) , new Person("李四", 15, 166) , new Person("张三", 19, 182) ).collect(Collectors.groupingBy(Person::getName)); map1.forEach((k,v)-> System.out.println("k=" + k +"\t"+ "v=" + v)); System.out.println("-----------"); // 根据年龄分组 如果大于等于18 成年否则未成年 Map<String, List<Person>> map2 = Stream.of( new Person("张三", 18, 175) , new Person("李四", 22, 177) , new Person("张三", 14, 165) , new Person("李四", 15, 166) , new Person("张三", 19, 182) ).collect(Collectors.groupingBy(p -> p.getAge() >= 18 ? "成年" : "未成年")); map2.forEach((k,v)-> System.out.println("k=" + k +"\t"+ "v=" + v)); }

          输出结果:

          k=李四 v=[Person{name='李四', age=22, height=177}, Person{name='李四', age=15, height=166}]
          k=张三 v=[Person{name='张三', age=18, height=175}, Person{name='张三', age=14, height=165}, Person{name='张三', age=19, height=182}]
          -----------
          k=未成年 v=[Person{name='张三', age=14, height=165}, Person{name='李四', age=15, height=166}]
          k=成年 v=[Person{name='张三', age=18, height=175}, Person{name='李四', age=22, height=177}, Person{name='张三', age=19, height=182}]

          多级分组: 先根据name分组然后根据年龄分组。

          public static void main(String[] args){ // 先根据name分组,然后根据age(成年和未成年)分组 Map<String,Map<Object,List<Person>>> map = Stream.of( new Person("张三", 18, 175) , new Person("李四", 22, 177) , new Person("张三", 14, 165) , new Person("李四", 15, 166) , new Person("张三", 19, 182) ).collect(Collectors.groupingBy( Person::getName ,Collectors.groupingBy(p->p.getAge()>=18?"成年":"未成年" ) )); map.forEach((k,v)->{ System.out.println(k); v.forEach((k1,v1)->{ System.out.println("\t"+k1 + "=" + v1); }); }); }

          输出结果:

          李四
          未成年=[Person{name='李四', age=15, height=166}]
          成年=[Person{name='李四', age=22, height=177}]
          张三
          未成年=[Person{name='张三', age=14, height=165}]
          成年=[Person{name='张三', age=18, height=175}, Person{name='张三', age=19, height=182}]

          对流中的数据做分区操作

          Collectors.partitioningBy会根据值是否为true,把集合中的数据分割为两个列表,一个true列表,一个false列表。

          public static void main(String[] args){ Map<Boolean, List<Person>> map = Stream.of( new Person("张三", 18, 175) , new Person("李四", 22, 177) , new Person("张三", 14, 165) , new Person("李四", 15, 166) , new Person("张三", 19, 182) ).collect(Collectors.partitioningBy(p -> p.getAge() > 18)); map.forEach((k,v)-> System.out.println(k+"\t" + v)); }

          输出结果:

          false [Person{name='张三', age=18, height=175}, Person{name='张三', age=14, height=165}, Person{name='李四', age=15, height=166}]
          true [Person{name='李四', age=22, height=177}, Person{name='张三', age=19, height=182}]

          对流中的数据做拼接

          Collectors.joining会根据指定的连接符,将所有的元素连接成一个字符串。

          public static void main(String[] args){ String s1 = Stream.of( new Person("张三", 18, 175) , new Person("李四", 22, 177) , new Person("张三", 14, 165) , new Person("李四", 15, 166) , new Person("张三", 19, 182) ).map(Person::getName) .collect(Collectors.joining()); // 张三李四张三李四张三 System.out.println(s1); String s2 = Stream.of( new Person("张三", 18, 175) , new Person("李四", 22, 177) , new Person("张三", 14, 165) , new Person("李四", 15, 166) , new Person("张三", 19, 182) ).map(Person::getName) .collect(Collectors.joining("_")); // 张三_李四_张三_李四_张三 System.out.println(s2); String s3 = Stream.of( new Person("张三", 18, 175) , new Person("李四", 22, 177) , new Person("张三", 14, 165) , new Person("李四", 15, 166) , new Person("张三", 19, 182) ).map(Person::getName) .collect(Collectors.joining("_", "###", "$$$")); // ###张三_李四_张三_李四_张三$$$ System.out.println(s3); }

          并行的Stream流

          Java8新特性有哪些亮点?

          串行的Stream流

          我们前面使用的Stream流都是串行,也就是在一个线程上面执行。

          并行流

          parallelStream其实就是一个并行执行的流,它通过默认的ForkJoinPool,可以提高多线程任务的速度。

          获取并行流

          我们可以通过两种方式来获取并行流。

          • 通过List接口中的parallelStream方法来获取
          • 通过已有的串行流转换为并行流(parallel)

          public static void main(String[] args){ List<Integer> list = new ArrayList<>(); // 通过List 接口 直接获取并行流 Stream<Integer> integerStream = list.parallelStream(); // 将已有的串行流转换为并行流 Stream<Integer> parallel = Stream.of(1, 2, 3).parallel(); }

          并行流操作

          public static void main(String[] args){ Stream.of(1,4,2,6,1,5,9) .parallel() // 将流转换为并发流,Stream处理的时候就会通过多线程处理 .filter(s->{ System.out.println(Thread.currentThread() + " s=" +s); return s > 2; }).count(); }

          并行流和串行流对比

          我们通过for循环,串行Stream流,并行Stream流来对500000000亿个数字求和。来看消耗时间。

          public class Test { private static long times = 500000000; private long start; @Before public void befor(){ start = System.currentTimeMillis(); } @After public void end(){ long end = System.currentTimeMillis(); System.out.println("消耗时间:" + (end - start)); } /** * 普通for循环 消耗时间:138 */ @Test public void test01(){ System.out.println("普通for循环:"); long res = 0; for (int i = 0; i < times; i++) { res += i; } } /** * 串行流处理 * 消耗时间:203 */ @Test public void test02(){ System.out.println("串行流:serialStream"); LongStream.rangeClosed(0,times) .reduce(0,Long::sum); } /** * 并行流处理 消耗时间:84 */ @Test public void test03(){ LongStream.rangeClosed(0,times) .parallel() .reduce(0,Long::sum); } }

          通过案例我们可以看到parallelStream的效率是最高的。

          Stream并行处理的过程会分而治之,也就是将一个大的任务切分成了多个小任务,这表示每个任务都是一个线程操作。

          线程安全问题

          在多线程的处理下,肯定会出现数据安全问题。如下:

          @Test public void test(){ List<Integer> list = new ArrayList<>(); for (int i = 0; i < 1000; i++) { list.add(i); } System.out.println(list.size()); List<Integer> listNew = new ArrayList<>(); // 使用并行流来向集合中添加数据 list.parallelStream() //.forEach(s->listNew.add(s)); .forEach(listNew::add); System.out.println(listNew.size());// 839 }

          针对这个问题,我们的解决方案有哪些呢?

          • 加同步锁
          • 使用线程安全的容器
          • 通过Stream中的toArray/collect操作

          以上就是Java8新特性 StreamAPI实例详解的详细内容,更多关于Java8新特性 StreamAPI的资料请关注自由互联其它相关文章!