史上最全的Stream流操作,赶紧收藏吧!

史上最全的Stream流操作,赶紧收藏吧!

首页休闲益智管道拼接更新时间:2024-05-09

上一篇文章说了Stream流的基础,Lambda表达式,今天我们就来看一下java8中强大的Stream流!

Stream流是Java8中引入的一个强大的功能,它允许我们以一种更加高效和简洁的方式处理集合、数组等数据结构中的元素。

Stream流的几个特点:

  1. 中间操作和终端操作:Stream 流的操作分为中间操作和终端操作。中间操作可以连接起来形成一个流水线,而终端操作会对流水线中的元素进行最终处理,并产生一个新的集合或值。
  2. 延迟执行:Stream 流的操作不会立即执行,而是等到需要结果的时候才执行。这种特性称为“惰性求值”,也就是当我们执行终端操作的时候整个流才会执行。
  3. 不存储数据源:Stream 流在操作过程中不会保存数据源中的元素,而是按照特定的规则对数据进行计算。
  4. 不改变数据源:Stream 流在操作过程中不会改变数据源,而是会产生一个新的集合或值,所以我们在执行完终端操作后需要返回新的数据源。

Stream流的操作步骤为:创建Stream、中间操作、终止操作(终端操作)并产生结果,接下来我们将分为这三部分章节进行讲解。

Stream串行流的创建

//集合 ArrayList<String> list = new ArrayList<>(); list.stream().forEach(System.out::println); String[] array = new String[10]; //数组 array[0]="a"; Arrays.stream(array).forEach(System.out::println);

Stream.of("aa","bb").forEach(System.out::println);

//如果不限制的话将会一直生成并输出 Stream.generate(Math::random).limit(4).forEach(System.out::println); //从0开始,每次加2,不限制将会一直输出 Stream.iterate(0, (integer)->integer 2).limit(4).forEach(System.out::println);Stream并行流的创建

ArrayList<String> list = new ArrayList<>(); list.add("1"); list.add("2"); list.add("3"); //并行流 list.parallelStream().forEach(System.out::println); //串行流 list.stream().forEach(System.out::println); //串行流改并行流 list.stream().parallel().forEach(System.out::println); //判断是否是并行流 System.out.println(list.stream().parallel().isParallel());

执行结果

并行流与串行流的区别

需要注意的是并行流并不总是比顺序流快。所以正确的姿势使用并行流是尤为重要的,不然适得其反(请注意线程安全问题)

中间操作

区分中间操作和终端操作的简单方法就是看是否返回的是Stream,如果是则是中间操作,否则是终端操作

//要求传入一个Predicate函数式接口并返回boolean作为筛选条件 Stream<T> filter(Predicate<? super T> predicate);

ArrayList<String> list = new ArrayList<>(); list.add("1"); list.add("2"); list.add("13"); list.add("12"); list.add("11"); //过滤集合中以1开头的字符串 list.stream().filter(x->x.startsWith("1")).forEach(System.out::println);

//要求传入一个Function函数式接口,传入集合参数,返回要转化的结果 <R> Stream<R> map(Function<? super T, ? extends R> mapper); //与上面的区别是当前流仅能转换为int类型,如果是其他数值类型,也会强转为int IntStream mapToInt(ToIntFunction<? super T> mapper); //与上面的区别是当前流仅能转换为long类型,如果是其他数值类型,也会强转为long LongStream mapToLong(ToLongFunction<? super T> mapper); //与上面的区别是当前流仅能转换为double类型,如果是其他数值类型,也会强转为double DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper);

ArrayList<String> list = new ArrayList<>(); list.add("1"); list.add("2"); list.add("13"); list.add("12"); list.add("11"); //将集合中的字符串参数转化为数字类型 list.stream().map(Integer::parseInt).forEach(System.out::println); list.stream().mapToInt(Integer::parseInt).forEach(System.out::println); list.stream().mapToDouble(Double::parseDouble).forEach(System.out::println); list.stream().mapToLong(Long::parseLong).forEach(System.out::println);

比map多了一个flat,flat的意思是平的、扁平的含义,操作的效果是对流的元素应用一对多转换,然后将生成的元素展平为新的流。话不多说我们直接上案例

<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper); IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper); LongStream flatMapToLong(Function<? super T, ? extends LongStream> mapper); DoubleStream flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper);

ArrayList<Company> companies = new ArrayList<>(); Staff wp = new Staff("王朋", "001"); Staff lm = new Staff("李明", "002"); Staff ly = new Staff("李艳", "003"); Staff wh = new Staff("王昊", "004"); Staff wm = new Staff("王明", "005"); Staff wz = new Staff("王中", "006"); Company company1 = new Company("字节跳动", Arrays.asList(wp,lm)); Company company2 = new Company("阿里巴巴", Arrays.asList(ly,wh)); Company company3 = new Company("华为", Arrays.asList(wm,wz)); companies.add(company1); companies.add(company2); companies.add(company3); companies.stream().map(Company::getStaffs).forEach(System.out::println); companies.stream().flatMap(x->x.getStaffs().stream()).forEach(System.out::println);

操作结果

看出来区别了吗,map的话只是把每个staff集合进行了输出;而flatmap的话是将每个staff集合中的数据再次拿出来遍历并输出。

去重依然是根据hashcode和queals方法进行,所以对于类我们需要重写这两个方法哦

Staff wp = new Staff("王朋", "001"); Staff lm = new Staff("李明", "002"); Staff ly = new Staff("李艳", "003"); ArrayList<Staff> staff = new ArrayList<>(); staff.add(wp); staff.add(lm); staff.add(ly); staff.add(new Staff("王朋","001")); staff.stream().distinct().forEach(System.out::println);

//类实现了Comparable接口的话可以直接调用 Stream<T> sorted(); //提供排序算法 Stream<T> sorted(Comparator<? super T> comparator);

ArrayList<Company> companies = new ArrayList<>(); Staff wp = new Staff("王朋", 1); Staff lm = new Staff("李明", 2); Staff ly = new Staff("李艳", 3); Staff wh = new Staff("王昊", 4); Staff wm = new Staff("王明", 5); Staff wz = new Staff("王中", 6); Company company = new Company("", Arrays.asList(wp, lm, ly, wh, wm, wz)); //从小按大排序 company.getStaffs().stream().sorted((o1,o2)->o1.getStaffNumber()-o2.getStaffNumber()).forEach(System.out::println); //也可以使用Comparator的静态方法 company.getStaffs().stream().sorted(Comparator.comparingInt(Staff::getStaffNumber)).forEach(System.out::println); //如果类实现类Comparable接口重写了排序方法的话,可以直接调用无参方法 company.getStaffs().stream().sorted().forEach(System.out::println);

Stream<T> limit(long maxSize);

ArrayList<Company> companies = new ArrayList<>(); Staff wp = new Staff("王朋", 1); Staff lm = new Staff("李明", 2); Staff ly = new Staff("李艳", 3); Staff wh = new Staff("王昊", 4); Staff wm = new Staff("王明", 5); Staff wz = new Staff("王中", 6); Company company = new Company("", Arrays.asList(wp, lm, ly, wh, wm, wz)); //限制数量为前三个 company.getStaffs().stream().limit(3).forEach(System.out::println);

peek的意思为偷看,他与我们后面讲的终端操作forEach很像,内部都是一个Consumer接口,唯一的区别是peek是中间操作而foreach是终端操作。peek可以debug的时候查看流中的数据是否有问题。

Stream<T> peek(Consumer<? super T> action);

ArrayList<Company> companies = new ArrayList<>(); Staff wp = new Staff("王朋", 1); Staff lm = new Staff("李明", 2); Staff ly = new Staff("李艳", 3); Staff wh = new Staff("王昊", 4); Staff wm = new Staff("王明", 5); Staff wz = new Staff("王中", 6); Company company = new Company("", Arrays.asList(wp, lm, ly, wh, wm, wz)); company.getStaffs().stream().peek(x->x.setStaffNumber(1)).forEach(System.out::println);

//很简单,指定跳过前几个就可以 Stream<T> skip(long n);

ArrayList<Company> companies = new ArrayList<>(); Staff wp = new Staff("王朋", 1); Staff lm = new Staff("李明", 2); Staff ly = new Staff("李艳", 3); Staff wh = new Staff("王昊", 4); Staff wm = new Staff("王明", 5); Staff wz = new Staff("王中", 6); Company company = new Company("", Arrays.asList(wp, lm, ly, wh, wm, wz)); //跳过前两个 company.getStaffs().stream().skip(2).forEach(System.out::println);

这是一个静态方法,意在将两个相同类型的流做连接并产生一个新的流

public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) { Objects.requireNonNull(a); Objects.requireNonNull(b); @SuppressWarnings("unchecked") Spliterator<T> split = new Streams.ConcatSpliterator.OfRef<>( (Spliterator<T>) a.spliterator(), (Spliterator<T>) b.spliterator()); Stream<T> stream = StreamSupport.stream(split, a.isParallel() || b.isParallel()); return stream.onClose(Streams.composedClose(a, b)); }

Staff wp = new Staff("王朋", 1); Staff lm = new Staff("李明", 2); Staff ly = new Staff("李艳", 3); Staff wh = new Staff("王昊", 4); Staff wm = new Staff("王明", 5); Staff wz = new Staff("王中", 6); Company company = new Company("", Arrays.asList(wp, lm, ly, wh, wm, wz)); Company company1 = new Company("", Arrays.asList(wp, lm, ly, wh, wm, wz)); Stream<Staff> concat = Stream.concat(company.getStaffs().stream(), company1.getStaffs().stream()); concat.forEach(System.out::println);

终端操作(terminal operation)

这个我们在上面一直在用,forEach并不会返回任何东西,它方法内部是一个消费型接口

//串行流的时候不能保证遍历的顺序 void forEach(Consumer<? super T> action);

Staff wp = new Staff("王朋", 1); Staff lm = new Staff("李明", 2); Staff ly = new Staff("李艳", 3); Staff wh = new Staff("王昊", 4); Staff wm = new Staff("王明", 5); Staff wz = new Staff("王中", 6); Company company = new Company("", Arrays.asList(wp, lm, ly, wh, wm, wz)); company.getStaffs().stream().forEach(x->x.setStaffNumber(1)); System.out.println(company.getStaffs());

//串行流的时候确保与原顺序一致,尤其是并行流的时候 void forEachOrdered(Consumer<? super T> action);

Staff wp = new Staff("王朋", 1); Staff lm = new Staff("李明", 2); Staff ly = new Staff("李艳", 3); Staff wh = new Staff("王昊", 4); Staff wm = new Staff("王明", 5); Staff wz = new Staff("王中", 6); Company company = new Company("", Arrays.asList(wp, lm, ly, wh, wm, wz)); company.getStaffs().stream().parallel().forEachOrdered(System.out::println); company.getStaffs().stream().parallel().forEach(System.out::println);

//将流转成Object数组 Object[] toArray(); //转成执行类型数组 <A> A[] toArray(IntFunction<A[]> generator);

Staff wp = new Staff("王朋", 1); Staff lm = new Staff("李明", 2); Staff ly = new Staff("李艳", 3); Staff wh = new Staff("王昊", 4); Staff wm = new Staff("王明", 5); Staff wz = new Staff("王中", 6); Company company = new Company("", Arrays.asList(wp, lm, ly, wh, wm, wz)); //默认返回的是一个Object数组 Object[] objects = company.getStaffs().stream().toArray(); //返回指定的类型 Staff[] staff = company.getStaffs().stream().toArray(new IntFunction<Staff[]>() { @Override public Staff[] apply(int value) { return new Staff[value]; } }); //使用方法引用 Staff[] staffArray = company.getStaffs().stream().toArray(Staff[]::new);

用于对流中的内容做计算操作,其中有三个重载方法

//给一个初始值,给一个计算过程 T reduce(T identity, BinaryOperator<T> accumulator); //不给初始值,默认是集合元素的第一个值,给一个计算过程 Optional<T> reduce(BinaryOperator<T> accumulator); //多一个参数,用于并行流计算 <U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner);

//T reduce(T identity, BinaryOperator<T> accumulator)实例: List<Integer> numbers = Arrays.asList(1, 3, 4, 5, 6, 7, 10); //求集合中的数值总和 //初始值为4 Integer sum = numbers.stream().reduce(4, new BinaryOperator<Integer>() { @Override public Integer apply(Integer integer, Integer integer2) { //第一个integer为每次计算的结果,首次为初始值 //第二个为流中的每个元素 //最终返回的值在下次便利时会赋值给integer System.out.println(Thread.currentThread().getName() ">>>integer>>>" integer ",integer2>>>>" integer2); return integer integer2; } }); System.out.println(sum); //最终结果40 //BinaryOperator接口提供了几个静态方法minBy、maxBy //其中maxBy为求最大值,将集合中的值于我们提供的默认值进行比较,返回最大值 Integer sum1 = numbers.stream().reduce(4, BinaryOperator.maxBy((o1,o2)->o1-o2)); //minBy为求最小值,将集合中的值于我们提供的默认值进行比较,返回最小值 Integer sum1 = numbers.stream().reduce(4, BinaryOperator.minBy((o1,o2)->o1-o2)); // Integer sum1 = numbers.stream().reduce(4, BinaryOperator.andThen((o1,o2)->o1-o2)); //需要注意的是当使用并行流时,每个线程的reduce的默认值都会是指定的默认值,怎么个意思,看例子 Integer parallelSum = numbers.stream().parallel().reduce(4, new BinaryOperator<Integer>() { @Override public Integer apply(Integer integer, Integer integer2) { System.out.println(Thread.currentThread().getName() ">>>integer>>>" integer ",integer2>>>>" integer2); return integer integer2; } }); System.out.println(parallelSum); //最终结果64

串行流时,我们发现正常在初始值的基础上进行累加;但是当是并行流时,每启动一个线程,我们的integer初始值都是4然后最终将每个线程的结果进行累加。

//Optional<T> reduce(BinaryOperator<T> accumulator)实例: List<Integer> numbers = Arrays.asList(1, 3, 4, 5, 6, 7, 10); //求集合中的数值总和 List<Integer> numbers = Arrays.asList(1, 3, 4, 5, 6, 7, 10); //在当前方法中,会将集合中的第一个值作为默认值,参考下图 Optional<Integer> reduce = numbers.stream().reduce(new BinaryOperator<Integer>() { @Override public Integer apply(Integer integer, Integer integer2) { System.out.println("integer:" integer); System.out.println("integer2:" integer2); return integer integer2; } }); System.out.println(reduce.get());

单参数实例

//<U> U reduce(U identity,BiFunction<U, ? super T, U> accumulator,BinaryOperator<U> combiner); List<Integer> numbers = Arrays.asList(1, 3, 4, 5, 6, 7, 10); Integer reduce = numbers.stream().reduce(0, new BinaryOperator<Integer>() { @Override public Integer apply(Integer integer, Integer integer2) { return integer integer2; } }, new BinaryOperator<Integer>() { @Override public Integer apply(Integer integer, Integer integer2) { return integer integer2; } });

将流转换为指定的集合

<R, A> R collect(Collector<? super T, A, R> collector); //第一个参数是提供一个基础容器,第二个是将集合参数转化为指定类型,第三个参数是将转化后的参数存入到指定容器中 <R> R collect(Supplier<R> supplier,BiConsumer<R, ? super T> accumulator,BiConsumer<R, R> combiner);

Staff wp = new Staff("王朋", 1); Staff lm = new Staff("李明", 2); Staff ly = new Staff("李艳", 3); Staff wh = new Staff("王昊", 4); Staff wm = new Staff("王明", 5); Staff wz = new Staff("王中", 6); Company company = new Company("字节跳动", Arrays.asList(wp, lm, ly, wh, wm, wz)); //将集合中的某些参数转化为map HashMap<String, Integer> hashMap = company.getStaffs().stream().collect(new Supplier<HashMap<String, Integer>>() { @Override public HashMap<String, Integer> get() { return new HashMap<String, Integer>(); } }, new BiConsumer<HashMap<String, Integer>, Staff>() { @Override public void accept(HashMap<String, Integer> hashMap, Staff staff) { hashMap.put(staff.getStaffName(), staff.getStaffNumber()); } }, new BiConsumer<HashMap<String, Integer>, HashMap<String, Integer>>() { @Override public void accept(HashMap<String, Integer> hashMap, HashMap<String, Integer> hashMap1) { hashMap.putAll(hashMap1); } }); System.out.println(hashMap);

//<R, A> R collect(Collector<? super T, A, R> collector); //对于这种,真要是写匿名内部类是非常麻烦的,但是java提供了Collectors工具类 Staff wp = new Staff("王朋", 1); Staff lm = new Staff("李明", 2); Staff ly = new Staff("李艳", 3); Staff wh = new Staff("王昊", 4); Staff wm = new Staff("王明", 5); Staff wz = new Staff("王中", 6); List<Staff> staffs = Arrays.asList(wp, lm, ly, wh, wm, wz); //转list List<Staff> list = staffs.stream().collect(Collectors.toList()); //转set Set<Staff> set = staffs.stream().collect(Collectors.toSet()); //转成任意你想要的集合 ArrayList<Staff> arrayList = staffs.stream().collect(Collectors.toCollection(new Supplier<ArrayList<Staff>>() { @Override public ArrayList<Staff> get() { return new ArrayList<Staff>(); } })); //按指定字段进行分组 Map<Integer, List<Staff>> collect = staffs.stream().collect(Collectors.groupingBy(new Function<Staff, Integer>() { @Override public Integer apply(Staff staff) { return staff.getStaffNumber(); } })); //先分组再求每组的数量 Map<Integer, Long> map = staffs.stream().collect(Collectors.groupingBy(Staff::getStaffNumber, Collectors.counting())); System.out.println(map); //先分组再求每组的数量,这里默认返回了1,实际上最终会将返回值相加 Map<Integer, Long> map1 = staffs.stream().collect(Collectors.groupingBy(Staff::getStaffNumber, Collectors.summingLong(new ToLongFunction<Staff>() { @Override public long applyAsLong(Staff value) { return 1; } }))); System.out.println(map1); //集合转map,key是StaffNumber,value是StaffName Map<Integer, String> map2 = staffs.stream().collect(Collectors.toMap(new Function<Staff, Integer>() { @Override public Integer apply(Staff staff) { return staff.getStaffNumber(); } }, new Function<Staff, String>() { @Override public String apply(Staff staff) { return staff.getStaffName(); } })); System.out.println(map2); //分组后对map的value字段进行再次处理,将List<Staff>转化为map,key为StaffNumber、value为StaffName Map<String, Map<Integer, String>> map3 = staffs.stream().collect(Collectors.groupingBy(Staff::getStaffName, Collectors.toMap(Staff::getStaffNumber, Staff::getStaffName))); System.out.println(map3); //多级分组,先按工号分,然后再在每组里按名字长短分 Map<Integer, Map<Integer, List<Staff>>> map4 = staffs.stream().collect(Collectors.groupingBy(Staff::getStaffNumber, Collectors.groupingBy(x -> x.getStaffName().length()))); System.out.println(map4); //集合转字符串拼接 List<String> list1 = Arrays.asList("a", "b", "c"); //abc System.out.println(list1.stream().collect(Collectors.joining())); //a,b,c System.out.println(list1.stream().collect(Collectors.joining(","))); //aa,b,cc System.out.println(list1.stream().collect(Collectors.joining(",","a","b"))); //求指定字段的数值运算 IntSummaryStatistics summaryStatistics = staffs.stream().collect(Collectors.summarizingInt(Staff::getStaffNumber)); //求和 long sum = summaryStatistics.getSum(); //平均值 double average = summaryStatistics.getAverage(); //最小值 int min = summaryStatistics.getMin(); //最大值 int max = summaryStatistics.getMax(); //总数量 long count = summaryStatistics.getCount(); System.out.println("sum:" sum ",average:" average ",min:" min ",max:" max ",count:" count);

获取当前集合中元素最小的一个

Optional<T> min(Comparator<? super T> comparator);

//获取工号最小的一个 Staff wp = new Staff("王朋", 1); Staff lm = new Staff("李明", 2); Staff ly = new Staff("李艳", 3); Staff wh = new Staff("王昊", 4); Staff wm = new Staff("王明", 5); Staff wz = new Staff("王中", 6); Company company = new Company("", Arrays.asList(wp, lm, ly, wh, wm, wz)); Optional<Staff> optionalStaff = company.getStaffs().stream().min(new Comparator<Staff>() { @Override public int compare(Staff o1, Staff o2) { return o1.getStaffNumber() - o2.getStaffNumber(); } }); if (optionalStaff.isPresent()) { Staff staff = optionalStaff.get(); System.out.println(staff); }

Optional不会的可以看之前的一篇文章:

获取当前集合中元素最大的一个

Optional<T> max(Comparator<? super T> comparator);

Staff wp = new Staff("王朋", 1); Staff lm = new Staff("李明", 2); Staff ly = new Staff("李艳", 3); Staff wh = new Staff("王昊", 4); Staff wm = new Staff("王明", 5); Staff wz = new Staff("王中", 6); Company company = new Company("", Arrays.asList(wp, lm, ly, wh, wm, wz)); Optional<Staff> optionalStaff = company.getStaffs().stream().max(new Comparator<Staff>() { @Override public int compare(Staff o1, Staff o2) { return o1.getStaffNumber() - o2.getStaffNumber(); } }); if (optionalStaff.isPresent()) { Staff staff = optionalStaff.get(); System.out.println(staff); }

求集合中的元素数量

long count();

Staff wp = new Staff("王朋", 1); Staff lm = new Staff("李明", 2); Staff ly = new Staff("李艳", 3); Staff wh = new Staff("王昊", 4); Staff wm = new Staff("王明", 5); Staff wz = new Staff("王中", 6); Company company = new Company("", Arrays.asList(wp, lm, ly, wh, wm, wz)); System.out.println(company.getStaffs().stream().count());

集合中是否有任意一个匹配指定条件的数据

boolean anyMatch(Predicate<? super T> predicate);

Staff wp = new Staff("王朋", 1); Staff lm = new Staff("李明", 2); Staff ly = new Staff("李艳", 3); Staff wh = new Staff("王昊", 4); Staff wm = new Staff("王明", 5); Staff wz = new Staff("王中", 6); Company company = new Company("", Arrays.asList(wp, lm, ly, wh, wm, wz)); System.out.println(company.getStaffs().stream().anyMatch(x -> "王朋".equals(x.getStaffName()))); //true

集合中是否所有元素都匹配指定条件的数据

boolean allMatch(Predicate<? super T> predicate);

Staff wp = new Staff("王朋", 1); Staff lm = new Staff("李明", 2); Staff ly = new Staff("李艳", 3); Staff wh = new Staff("王昊", 4); Staff wm = new Staff("王明", 5); Staff wz = new Staff("王中", 6); Company company = new Company("字节跳动", Arrays.asList(wp, lm, ly, wh, wm, wz)); System.out.println(company.getStaffs().stream().allMatch(x -> "王朋".equals(x.getStaffName()))); //false

集合中是否所有元素都不匹配指定条件的数据

boolean noneMatch(Predicate<? super T> predicate);

Staff wp = new Staff("王朋", 1); Staff lm = new Staff("李明", 2); Staff ly = new Staff("李艳", 3); Staff wh = new Staff("王昊", 4); Staff wm = new Staff("王明", 5); Staff wz = new Staff("王中", 6); Company company = new Company("字节跳动", Arrays.asList(wp, lm, ly, wh, wm, wz)); System.out.println(company.getStaffs().stream().noneMatch(x -> "王坤".equals(x.getStaffName()))); //ture

在流中获取第一个

Optional<T> findFirst();

Staff wp = new Staff("王朋", 1); Staff lm = new Staff("李明", 2); Staff ly = new Staff("李艳", 3); Staff wh = new Staff("王昊", 4); Staff wm = new Staff("王明", 5); Staff wz = new Staff("王中", 6); Company company = new Company("字节跳动", Arrays.asList(wp, lm, ly, wh, wm, wz)); Optional<Staff> first = company.getStaffs().stream().findFirst(); if (first.isPresent()) { System.out.println(first.get()); } //Staff{staffName='王朋', staffNumber='1'} //上面的判断也可以替换为: first.ifPresent(System.out::println);

获取任意一个值

Optional<T> findAny();

Staff wp = new Staff("王朋", 1); Staff lm = new Staff("李明", 2); Staff ly = new Staff("李艳", 3); Staff wh = new Staff("王昊", 4); Staff wm = new Staff("王明", 5); Staff wz = new Staff("王中", 6); Company company = new Company("字节跳动", Arrays.asList(wp, lm, ly, wh, wm, wz)); Optional<Staff> first = company.getStaffs().stream().findAny(); first.ifPresent(System.out::println);,

大家还看了
也许喜欢
更多游戏

Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved