一、什么是stream

  • 在 java8 中增加了一个新的抽象接口 Stream API,使用 Stream 操作集合类似于使用 SQL 语句数据库查找数据类似,提供直观的方法进行操作。

  • Stream 将要处理的元素集合看作是一种流,流在管道中传输,并且可以在管道传输过程中对流进行处理,比如筛选、排序、聚合等操作

  • 一个Java8 的stream是由三部分组成的。数据源,零个或一个或多个中间操作,一个或零个终止操作。

  • 中间操作是对数据的加工,注意,中间操作是lazy操作,并不会立马启动,需要等待终止操作才会执行。终止操作是stream的启动操作,只有加上终止操作,stream才会真正的开始执行。

二、Stream操作分类

Stream 操作分为 中间操作、终端操作,信息如下:

Stream操作分类
中间操作 无状态 unordered()、filter()、map()、mapToInt()、mapToLong() mapToDouble()、flatMap()、flatMapToInt()、flatMapToLong() flatMapToDouble()、peek()
有状态 distinct()、sorted()、limit()、skip()
终端操作 非短路操作 forEach()、forEachOrdered()、toArray()、reduce()、collect、max()、min()、count()
短路操作 anyMatch()、allMatch()、noneMatch()、findFirst()、findAny()
  • 中间操作总是会惰性执行:中间操作其实就是进行逻辑处理,会生成一个标记了该操作的新Stream,这个操作可以有一个或多个连续操作,将一个流转换成另一个流,这些操作不会消耗流,其目的是建立一个流水线,直到终端操作发生后,才会做数据的最终执行。

    • 无状态:指数据处理时,不受之前“中间操作”的影响

    • 有状态:指数据处理时,受之前“中间操作”的影响,有状态的方法往往需要更大的性能开销

  • 终端操作会触发实际结果:一个Stream对象只能有一个终端操作,这个操作一旦发生,就会把所有中间操作积攒的操作以管道的方式执行,这样可以减少迭代次数,生成对应的处理结果,最终stream失效。
    • 非短路操作:指必须处理所有元素才能得到最终结果

    • 短路操作:指遇到某些符合条件的元素就可以得到最终结果

区分中间操作和结束操作最简单的方法,就是看方法的返回值,返回值为stream的大都是中间操作,否则是结束操作。

三、Stream特性

  • 无存储:Stream不会对数据进行存储,而是按照特定的规则对数据进行处理

  • 不改变数据源:Stream通常不会改变原有数据源,操作时一般是对原有的数据源创建副本,然后对副本进行处理,生成新的Stream

  • 具有懒惰化:Stream 很多操作是有向后延迟的,需要一直等到它弄清楚了最后需要多少数据才会开始。而中间操作永远是惰性化的。

  • 可以是无限的:集合有固定大小,Stream则不一定。limit(n)和findFirst()这类的短路操作,可以对无限的Stream快速完成运算处理。

  • 支持并行能力:Stream是支持并行能力的,可以轻松执行并行化对数据进行处理

  • 可被消耗的:Stream的生命周期中,Stream的元素只被消费一次。与迭代器一样,必须生成新的Stream后,才能重新访问与开始源中相同的元素。

四、数据转换为Stream

一般我们需要获取 Stream 对象后才能对其进行操作,下面列出了一些数据转换为 Stream 的常用方法:

    /** 数据转换为Stream */@Testpublic void a1() {// 多个数据直接转换为StreamStream<String> stream1 = Stream.of("a", "b", "c");System.out.println(stream1);  // java.util.stream.ReferencePipeline$Head@33d53216// 数组转换为 StreamString[] strArrays = {"a", "b"};Stream<String> stream2 = Arrays.stream(strArrays);System.out.println(stream2);  // java.util.stream.ReferencePipeline$Head@69a2b3b6// list列表转换为 StreamArrayList<String> strList = new ArrayList<>();strList.add("a");strList.add("b");Stream<String> stream3 = strList.stream();System.out.println(stream3);  // java.util.stream.ReferencePipeline$Head@4f3e7344// set 集合转换为 StreamSet<String> strSet = new HashSet<>();strSet.add("a");strSet.add("b");Stream<String> stream4 = strSet.stream();System.out.println(stream4);   // java.util.stream.ReferencePipeline$Head@7808f638// map集合转换为StreamHashMap<String, Integer> map = new HashMap<>();map.put("a", 100);map.put("b", 200);Stream<Map.Entry<String, Integer>> stream5 = map.entrySet().stream();System.out.println(stream5);  // java.util.stream.ReferencePipeline$Head@62d73ead}

五、Stream转换得到指定类型数据

既然可以把集合或者数组转换成流,那么也就可以把流转换回去,使用collect()方法就能实现,不过一般还需要配合 Collectors 工具类一起使用, Collectors 类中内置了一系列收集器实现,如下:

  • toList():将元素收集到一个新的 List 集合中

  • toSet():将元素手机到一个新的 Set 集合中

  • toCollection():将元素收集到一个新的 ArrayList 集合中

  • joining():将元素收集到一个可以用分隔符指定的字符串中

/** Stream 转换得到指定类型数据 */@Testpublic void a2() {// Stream 转换位字符串Stream<String> stream2 = Stream.of("a", "b", "c", "a");String str = stream2.collect(Collectors.joining()).toString();System.out.println(str);   // abca// Stream 转换为 List列表List<String> strList = stream2.collect(Collectors.toList());System.out.println(strList);   // [a, b, c, a]// Stream转换为Set集合Set<String> collect1 = stream2.collect(Collectors.toSet());System.out.println(collect1);  // [a, b, c]}

六、Stream对于基本类型的封装

因为Java的泛型不支持基本类型,所以我们无法用 Stream<int> 这样的类型,如果写了类似代码在编译器中会提示编译错误。为了存储int,只能使用 Stream<Integer> ,但这样会产生频繁的装箱、拆箱操作。为了提高效率,对基本类型 int、long、double 进行了封装,分别为 IntStream、LongStream、DoubleStream,使用方法和 Stream类似,示例代码如下:

/** Stream 对于基本类型的封装 */@Testpublic void a4() {// IntStreamIntStream.of(new int[]{10,20,30}).forEach(System.out::println); // 10 20 30IntStream.range(1,5).forEach(System.out::println);          // 1 2 3 4IntStream.rangeClosed(1,5).forEach(System.out::println);    // 1 2 3 4 5// LongStreamLongStream.of(new long[]{1L, 2L, 3L}).forEach(System.out::println);  // 1 2 3LongStream.range(1,5).forEach(System.out::println);          // 1 2 3 4LongStream.rangeClosed(1,5).forEach(System.out::println);    // 1 2 3 4 5// DoubleStreamDoubleStream.of(1.11, 2.23, 3.14).forEach(System.out::println);  // 1.11  2.23  3.14}

七、Stream的串行与并行

  1. Stream的并行介绍

在Stream中,最明显的特点就是存在并行操作,不过如果使用默认方式执行中间与终端操作,那么整个执行过程其实是串行操作。如果想让Stream并行处理数据,那么需要Stream中调用parallel()或者集合中调用parallelStream()方法来开启并行执行。

@Test
public void a5() {List<String> list = Arrays.asList("One", "Two", "three", "Four", "Five");Stream<String> stream = list.stream().parallel();System.out.println(stream);// 第二种写法Stream<String> stringStream = list.parallelStream();System.out.println(stringStream);
}

其中Stream底层使用的是 ForkJoinTask 实现 Stream的并行处理,充分利用CPU 的多核能力,Stream的API将底层复杂实现完全屏蔽了,开发者仅需调用一个方法即可实现并行计算。

2.Stream的串行和并行运行时间

@Testpublic void a5() {//并行计算long startTime = System.currentTimeMillis();System.out.println(startTime);long sumResult1 = LongStream.rangeClosed(1, 10000000000L).parallel().sum();System.out.println(System.currentTimeMillis() - startTime);  // 1384// 串行计算startTime = System.currentTimeMillis();long sumResult2 = LongStream.rangeClosed(1, 10000000000L).sum();System.out.println(System.currentTimeMillis() - startTime);  // 4134}

可以看到使用并行执行所花费的时间远低于串行所花费的时间,不过在使用并行执行时一定要先考虑好使用情况,考虑执行数据是否需要顺序执行,是否涉及线程安全,是否涉及使用网络等。

八、Stream中间操作(有状态)常用API

stream跟函数接口关系非常紧密,没有函数接口stream就无法工作。回顾一下:函数接口是指内部只有一个抽象方法的接口。通常函数接口出现的地方都可以使用Lambda表达式,所以不必记忆函数接口的名字。

1、distinct 去重

  • 保证输出的流中包含唯一的元素,通常用于数据去重。
  • 接口定义: Stream<T> distinct();
  • 方法描述:在distinct 接口定义中不接收任何参数,该方法的作用是根据 hashCode() 和 equals() 方法来获取不同的元素,因此我们的元素必须实现这两个方法。如果distinct() 正在处理有序流,那么对于重复元素将保留元素时的顺序。而在处理无序流的情况下,则不一定保证元素的顺序。在有序流的并行执行情况下,保持distinct() 的顺序性是需要高昂的缓冲开销。如果我们在处理元素时,不需要保证元素的顺序性,那么我们可以使用 unordered() 方法来实现无序流。
/** distinct() 方法 */@Testpublic void a6() {List<Integer> strList = new ArrayList<>();strList.add(4);strList.add(2);strList.add(2);strList.add(1);strList.add(3);strList.stream().distinct().unordered().forEach(System.out::println);  // 4 2 1 3}
// 项目中的案例  优势就是不需要再写去重的sql语句
// 有状态:指数据处理时,受之前“中间操作”的影响,有状态的方法往往需要更大的性能开销
List<String> orgIdList = programDimensionList.stream().map(BackcalProgramDimension::getOrganizationId).distinct().collect(Collectors.toList());

2、sorted 排序

对数据进行排序,不过对于有序流,排序是稳定的,而对于非有序流,不保证排序稳定。

  • 接口定义:Stream<T> sorted();   Stream<T> sorted(Comparator<? super T> comparator);
  • 方法描述:
    • 使用 Stream<T> sorted(); 方法时,它会将 Stream中的元素按照 自然排序 方式对元素进行排序。等到将全部元素处理完成后,将元素组成新的Stream返回。

    • 使用 Stream<T> sorted(Comparator<? super T> comparator); 方法时,它接收的是一个 Comparator 类型参数,在Lambda表达式中 Comparator<T> 一般是用于比较两个参数,设计一个算法逻辑,执行完后返回一个整数,可以是负数、零、正整数,它的不同的值表示两个值比较的不同,一般排序会按这个比较结果进行排序。等到将全部元素处理完成后,将元素组成新的 Stream 返回。

/** sorted 方法 */@Testpublic void a7() {List<Integer> strList = new ArrayList<>();strList.add(4);strList.add(2);strList.add(1);strList.stream().sorted((x, y) -> x-y).forEach(System.out::println); // 1  2  4 用了比较器进行比较 从小到大}
// 项目中用到的排序,不是自然排序,通过比较器进行比较,如果从高到低,比较器后面加上reversed(),最后获取的是 getVariableCode这个字段的值
List<String> variableCodeList = variableList.stream().sorted(Comparator.comparing(CalculationVariable::getVariableCode).reversed()).map(f -> f.getVariableCode()).distinct().collect(Collectors.toList());

3、skip 跳过

根据指定数值,从指定位置跳过流中某些元素

  • 接口定义: Sream<T> skip(long n);
  • 方法描述:在skip接口定义中是接收 long 类型参数,指定要跳过前n个元素,将第n个后的元素组成新的流返回
/** skip 方法 */@Testpublic void a8() {List<Integer> strList = new ArrayList<>();strList.add(1);strList.add(2);strList.add(3);strList.stream().skip(2).forEach(System.out::println);  // 3}

4、limit 限制展示几个

根据指定数值,限制只能访问流中最大访问的个数。这是一个有状态的、短路方法。

  • 接口定义:Stream<T> limit(long maxSize);
  • 方法描述:在limit 接口定义中是接收 long 类型参数,指定限制 maxSize 个元素,即将 maxSize 和它之前的元素组成新的流返回
/** limit 方法 */@Testpublic void a9() {List<Integer> strList = new ArrayList<>();strList.add(1);strList.add(2);strList.add(3);strList.add(4);strList.add(5);strList.stream().limit(2).forEach(System.out::println);  //  1  2}

九、Stream中间操作(无状态)常用API

1、map

对流中的元素进行处理,然后返回,返回值的类型可以和原来的元素的类型不同

  • 接口定义:Stream<R> map(Function<? super T, ? extends R> mapper);
  • 方法描述:在map接口定义中是接收 Function 类型参数,了解 Lambda 表达式就可以知道 Function<T,R> 是接收一个 T 返回处理后的值 R。所以,这里map方法就是对流中的元素进行处理,然后返回一个新的元素。等到将全部元素处理完成后将元素组成新的流返回。
/** map */@Testpublic void a10() {List<String> strList = new ArrayList<>();strList.add("zhangsan");strList.add("lisi");strList.add("wangwu");strList.add("zhaoliu");strList.add("sunqi");strList.stream().map(x -> "测试:" + x).collect(Collectors.toList()).forEach(System.out::println);}
测试:zhangsan
测试:lisi
测试:wangwu
测试:zhaoliu
测试:sunqi
// 项目中的案例
// 判断考核期是否存在考核期表内
boolean isExitPeriod = periodList.stream().map(Period::getPeriod).collect(Collectors.toList()).contains(period);

2、peek

对流中的每个元素进行操作处理,返回的流和原来的流保存一样的元素

  • 接口定义:Stream<T> peek(Consumer<? super T> action);
  • 方法描述:在peek 接口定义中是接收 Consumer 类型参数,了解 Lambda 表达式就可以知道 Consumer<T> 是接收一个T返回处理后不返回值。所以,这里peek方法就是对流中的元素进行处理而不返回值。等到将全部元素处理完成后将元素组成新的流返回。
/** peek */@Testpublic void a11() {List<String> strList = new ArrayList<>();strList.add("zhangsan");strList.add("lisi");strList.add("wangwu");strList.stream().peek(x -> System.out.println("forEach 1:" + x)).peek(x -> System.out.println("forEach 2:" + x)).forEach(System.out::println);}forEach 1:zhangsan
forEach 2:zhangsan
zhangsan
forEach 1:lisi
forEach 2:lisi
lisi
forEach 1:wangwu
forEach 2:wangwu
wangwu

自己对peek的理解,就是对stream流中的元素输出单个的值,方便调式,方便看到每个变量的值。

3、filter

主要用于数据过滤,过滤不符合 predicate 条件的元素,保留过滤后的元素

  • 接口定义: Stream<T> filter(Predicate<? super T> predicate);
  • 方法描述: 在 filter 接口定义中是接收 Predicate 类型参数,了解Lambda表达式就可以知道 Predicate<T> 是接收一个T进行验证,返回布尔值。所以,这里filter方法就是设置验证条件,对流中的元素进行验证,返回符合条件的全部元素组成新的流。
/** filter */@Testpublic void a12() {List<String> strList = new ArrayList<>();strList.add("zhangsan");strList.add("lisi");strList.add("wangwu");strList.add("zhaoliu");strList.add("sunqi");strList.stream().filter(x -> x.length()>5).collect(Collectors.toList()).forEach(System.out::println);}
zhangsan
wangwu
zhaoliu

4、mapToInt

主要用于对流中元素进行一对一转换为int整数,然后可以进行一些求和、平均值、最大最小值等处理。

  • 接口定义:IntStream mapToInt(ToIntFunction<? super T> mapper);
  • 方法描述:在mapToInt 接口定义中可知,它接收 ToIntFunction 类型参数,在Lambda中ToIntFunction<T> 函数的作用为接收一个输入参数,返回一个int 类型结果,根据这点很容易了解到mapToInt方法就是将Stream中原有的元素类型转换为int类型到新的Stream中。
/** mapToInt */@Testpublic void a13() {Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);int max = integerStream.mapToInt(x -> x).summaryStatistics().getMax();System.out.println(max);  // 10IntSummaryStatistics intSummaryStatistics = integerStream.mapToInt(x -> x).summaryStatistics();System.out.println(intSummaryStatistics);  // IntSummaryStatistics{count=10, sum=55, min=1, average=5.500000, max=10}}
// 项目中使用到的示例:
workDay = BigDecimal.valueOf(workDayCountListGroupById.get(employeeId).stream().mapToInt(PorationModel::getCount).sum());

5、mapToDouble

主要用于对流中元素进行一对一转换为double双精度浮点数,然后可以进行一些求和、平均值、最大最小值等处理。

  • 接口定义:DoubleStream mapToDouble(ToIntFunction<? super T> mapper);
  • 方法描述:在 mapToDouble 接口定义中可知,它接收 ToDoubleFunction 类型参数,在Lambda中ToDoubleFunction <T> 函数的作用为接收一个输入参数,返回一个Double类型结果,根据这点很容易了解到mapToDouble 方法就是将Stream中原有的元素类型转换为Double类型到新的Stream中。
/** mapToDouble */@Testpublic void a14() {Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);double max = integerStream.mapToDouble(x -> x).summaryStatistics().getMax();System.out.println(max);  // 10.0DoubleSummaryStatistics doubleSummaryStatistics = integerStream.mapToDouble(x -> x).summaryStatistics();System.out.println(doubleSummaryStatistics);  // DoubleSummaryStatistics{count=10, sum=55.000000, min=1.000000, average=5.500000, max=10.000000}}

十、Stream终端操作(短路操作)常用API

1、anyMatch      anyMatch和allMatch和noneMatch的区别详解

2、allMatch        anyMatch和allMatch和noneMatch的区别详解

3、noneMatch    anyMatch和allMatch和noneMatch的区别详解

4、findFirst

返回第一个元素,如果流为空,返回空的Optional对象。

  • 接口定义:Optional<T> findFirst();
  • 方法描述:在 findFirst 方法的作用是返回集合中的第一个对象
/*** findFirst*/@Testpublic void a21() {List<User> list = new ArrayList<>();list.add(new User("张三", 12, "南京"));list.add(new User("李四", 13, "北京"));list.add(new User("王五", 14, "苏州"));list.add(new User("王五", 17, "苏州"));Optional<User> user = list.stream().filter(a -> a.getName().equals("王五")).findFirst();if (user.isPresent()) {System.out.println(user.get().getAge());   // 14} else {System.out.println("查无此人");}}
// 项目中用到过的示例
Optional<MailDataSourceRelation> relation = relationList.stream().filter(f -> f.getColumnKey().equals(item.getColumnKey())).findFirst();
if (relation.isPresent()) {item.setIsUsed("Y");
}

5、findAny

返回任意一个元素,如果流为空,返回空的Optional对象。

  • 接口定义:Optional<T> findAny();
  • 方法描述:在 findAny 方法的作用是返回集合中的任何一个对象。
/*** findAny
*/
@Test
public void a22() {List<User> list = new ArrayList<>();list.add(new User("张三", 12, "南京"));list.add(new User("李四", 13, "北京"));list.add(new User("王五", 14, "苏州"));list.add(new User("王五", 17, "苏州"));Optional<User> user = list.stream().filter(a -> a.getName().equals("王五")).findAny();if (user.isPresent()) {System.out.println(user.get().getAge());   // 14}
}
// 项目中用到过的示例 经常跟isPresent配合使用
if(list.stream().filter(x -> !x.getId().equalsIgnoreCase(item.getId()) && x.getIndicatorCode().equalsIgnoreCase(item.getIndicatorCode())).findAny().isPresent()){throw ExpResult.fail("权重项代码已经存在");
}

十一、Stream终端操作(非短路操作)常用API

1、max

返回流中所有元素的最大值

  • 接口定义:Optional<T> max(Comparator<? super T> comparator);
  • 方法描述:在 max接口定义中接收Comparator类型参数,Lambda常用函数的Consumer<T> 一般是用于比较两个参数,设置一个算法逻辑,执行完后返回一个整数,可以是负数、零、正整数,根据返回的值结果进行排序筛选出最大值。
 /*** max 使用
*/
@Test
public void a24() {Stream<Integer> stream = Stream.of(1, 3, 5, 8);Optional<Integer> max = stream.max((x, y) -> x - y);if (max.isPresent()) {System.out.println(max.get());  // 8}
}

2、min

返回流中所有元素的最小值

  • 接口定义:Optional<T> min(Comparator<? super T> comparator);
  • 方法描述:在 min接口定义中接收Comparator类型参数,Lambda常用函数的Consumer<T> 一般是用于比较两个参数,设置一个算法逻辑,执行完后返回一个整数,可以是负数、零、正整数,根据返回的值结果进行排序筛选出最小值。
/*** min 使用
*/
@Test
public void a25() {Stream<Integer> stream = Stream.of(1, 3, 5, 8);Optional<Integer> min = stream.min(Integer::compareTo);if (min.isPresent()) {System.out.println(min.get());  // 1}
}
//项目中使用到的示例
Optional<MeasurementTierSetting> hopsOptional = hopsList.stream().min(Comparator.comparing(MeasurementTierSetting::getRowSeq));

3、count

返回流中所有元素的数目

  • 接口定义:long count();
  • 方法描述:该方法用于统计stream中元素个数,返回long类型结果。
/*** count 使用*/
@Test
public void a26() {Stream<Integer> stream = Stream.of(1, 3, 5, 8);long count = stream.count();System.out.println(count);  // 4
}
//项目中使用到的示例
long count = ruleAndCommissionItemRelationHistoryList.stream().filter(e -> e.getCommissionItemId().equals(commissionItemId)).count();
if (count > 0) {commissionItemIds.add(commissionItemId);
}

4、reduce

主要用于对数据进行合并处理 (对字段的值进行相加或者多字段的值进行相加)

  • 接口定义:

5、forEach

主要用于对数据遍历整个流中元素,执行指定逻辑,在并发执行时不保证顺序。

  • 接口定义:void forEach(Consumer<? super T> action);
  • 方法描述:对 Stream 中的每个元素都执行一段逻辑代码,例如,循环打印输出元素的值,但是需要注意的是,在并发执行时无法保证执行顺序。
/*** forEach使用*/
@Test
public void a30() {Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);stream.forEach(System.out::println);
}

6、forEachOrdered

主要用于对数据遍历整个流中元素,执行指定逻辑,在并发执行时保证顺序

  • 接口定义: void forEachOrdered(Consumer<? super T> action);
  • 方法描述:对 Stream 中的每个元素都执行一段逻辑代码,例如,循环打印输出元素的值,但是需要注意的是,在并发执行时无法保证执行顺序。
/*** forEachOrdered*/
@Test
public void a31() {Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);stream.parallel().forEachOrdered(System.out::println);
}

7、toArray

将Stream流中的数据存储到数组中

  • 接口定义:Object[] toArray();    <A>A[] toArray(IntFunction<A[]> generator);
  • 方法描述:将 Stream 中的元素,存储到Object 数组
/*** toArray*/
@Test
public void a32() {Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);Object[] objectArray = stream.toArray();Arrays.stream(objectArray).forEach(System.out::println);
}

8、collect

常用的聚合方法,能将数据进行聚合操作。不仅如此,它还能与Controller配合使用,对聚合后的数据进行处理。

【Stream】java8新特性Stream流总结相关推荐

  1. java8新特性stream流

    参考自深蓝至尊的Java8 新特性之流式数据处理 一. 流式处理简介 在我接触到java8流式处理的时候,我的第一感觉是流式处理让集合操作变得简洁了许多,通常我们需要多行代码才能完成的操作,借助于流式 ...

  2. Java8新特性Stream流详解

    陈老老老板 说明:新的专栏,本专栏专门讲Java8新特性,把平时遇到的问题与Java8的写法进行总结,需要注意的地方都标红了,一起加油. 本文是介绍Java8新特性Stream流常用方法超详细教学 说 ...

  3. List 集合去重方式与 java8新特性stream去重

    以下介绍五种 - 不同的方法去除 Java 中 ArrayList 中的重复数据 1.使用 LinkedHashSet 删除 arraylist 中的重复数据 LinkedHashSet 是在一个 A ...

  4. java8新特性-stream对map集合进行过滤的方法

    java8新特性-stream对map集合进行过滤的方法 stream对map集合进行过滤的方法

  5. java8新特性-Stream入门学习

    上一篇介绍了Lambda的学习,如果对Lambda表达式还不清晰的同学可以戳一下这个链接:java8新特性-lambda表达式入门学习.java8除了提供了Lambda表达式,操作集合的Stream ...

  6. Java8 新特性之流式数据处理(转)

    转自:https://www.cnblogs.com/shenlanzhizun/p/6027042.html 一. 流式处理简介 在我接触到java8流式处理的时候,我的第一感觉是流式处理让集合操作 ...

  7. Java8新特性——Stream流:不同于IO流的流,操作集合数据

    文章目录 Stream流 1.认识Stream流(源码说明) 1.1.Stream流和Collection的区别 1.2.流的获取方式 1.3.流操作和管道 1.4.并行性 1.5.不干扰内政 1.6 ...

  8. java8新特性 Stream流的优雅操作

    1. 使用传统的方式,遍历集合,对集合中的数据进行过滤 //创建一个List集合,存储姓名List<String> list = new ArrayList<>();list. ...

  9. java8新特性-Stream流

    直接贴代码: package com.c8a.stream;import lombok.AllArgsConstructor; import lombok.Data; import lombok.No ...

最新文章

  1. spring oauth2+JWT后端自动刷新access_token
  2. Exchange Server 2013 DAG高可用部署(四)-服务器配置(上)
  3. esxi虚拟化集群_ProxmoxVE 之集群安装(V5.2)
  4. 面试题之第一部分(Python基础篇) 80题
  5. 使用ffmpeg合并视频文件的三种方法
  6. textview加载html glide,TextView加载HTML,文字和图片
  7. MySQL 四种事务隔离级的说明
  8. MySql解决办法:2004:Can't create TCP/IP socket (24)
  9. 互联网大佬生存法则:如何防守周鸿祎?
  10. JAVA安卓植物大战僵尸主题四子棋游戏
  11. Fundamentals Of Computer Graphics (4th Ed)
  12. 零基础语法入门三十一讲[被动语态 (1)]被动语态的构成和含义
  13. 网络爬虫异常处理总结
  14. 三星手机com.android.systemservice卸载,完美卸载 系统程序卸载就用System App Remover
  15. win7旗舰版通知windows不是正版副本解决方法
  16. 基于python的数据爬虫学习与体会
  17. 从NAACL2021到ACL2022:两个信息抽取SOTA的比较分析(PURE vs PL-Marker)
  18. keras 使用WGAN-div进行图像生成
  19. 域策略(2)——设置统一桌面背景
  20. c语言课程设计 选课系统,学生选课系统c语言课程设计.doc

热门文章

  1. SAP 固定资产期初导入
  2. win10下载文件夹变成英文了该怎么办?下载文件夹变成英文的修复方法
  3. 解决linux不能上外网
  4. 深圳高中计算机老师招聘,深圳一所高中招聘20位老师,19人来自清华北大
  5. 铁威马F2-NAS2评测(家用云存储NAS)
  6. 分水岭算法(学习笔记)
  7. 【Excel提取数字】用5个简单公式从混合文本中提取数字
  8. 如何创建一张属于自己的简单的网页
  9. opencv中 idft与 mathlab中 ifft2结果不对应的解决方案
  10. RESLAM/ REVO 编译 实时RGBD基于边缘的slam系统