写点什么

Java8 新特性 -Stream,java 数据结构和算法 pdf 百度云

用户头像
极客good
关注
发布于: 刚刚

stream.forEach(System.out::println);


}


输出结果


a


b


c


d

[](

)通过数组创建流


@Test


public void testArrayStream() {


int[] arr = new int[]{1, 2, 3, 4};


IntStream intStream = Arrays.stream(arr);


intStream.forEach(System.out::println);


System.out.println("========");


Integer[] arr2 = new Integer[]{1, 2, 3, 4};


Stream<Integer> stream = Arrays.stream(arr2);


stream.forEach(System.out::println);


}


输出结果


1


2


3


4


========


1


2


3


4

[](

)通过 Stream.of 方法创建流


@Test


public void testStreamOf() {


Stream<Integer> stream = Stream.of(1, 2, 3);


stream.forEach(System.out::println);


}


输出结果


1


2


3

[](

)创建规律的无限流


@Test


public void testUnlimitStream() {


Stream<Integer> stream = Stream.iterate(0, x -> x + 2).limit(3);


stream.forEach(System.out::println);


}


输出结果


0


2


4

[](

)创建无限流


@Test


public void testUnlimitStream2() {


Stream<String> stream = Stream.generate(() -> "number" + new Random().nextInt()).limit(3);


stream.forEach(System.out::println);


}


输出结果


number1042047526


number-155761434


number-1605164634

[](

)创建空流


@Test


public void testEmptyStream() {


Stream<Integer> stream = Stream.empty();


stream.forEach(System.out::println);


}


[](


)Stream 操作分类




  • 中间操作又可以分为无状态(Stateless)与有状态(Stateful)操作,

  • 无状态是指元素的处理不受之前元素的影响,

  • 有状态是指该操作只有拿到所有元素之后才能继续下去。

  • 终结操作又可以分为短路(Short-circuiting)与非短路(Unshort-circuiting)操作,

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

  • 非短路是指必须处理完所有元素才能得到最终结果。

  • 我们通常还会将中间操作称为懒操作,也正是由这种懒操作结合终结操作数据源构成的处理管道(Pipeline)实现了 Stream 的高效



[](


)中间操作



[](

)无状态


  • filter:过滤流,过滤流中的元素

  • map:转换流,将一种类型的流转换为另外一种类型的流

  • flapMap:拆解流,将流中每一个元素拆解成一个流

[](

)filter


filter 接收一个 Predicate 函数接口参数,boolean test(T t);即接收一个参数,返回 boolean 类型。


@Test


public void testFilter() {


Integer[] arr = new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};


Arrays.stream(arr).filter(x -> x > 3 && x < 8).forEach(System.out::println);


}


输出结果


4


5


6


7

[](

)map


map 接收一个 Function<T, R>函数接口,R apply(T t);即接收一个参数,并且有返回值。


@Test


public void testMap() {


String[] arr = new String[]{"yes", "YES", "no", "NO"};


Arrays.stream(arr).map(x -> x.toLowerCase()).forEach(System.out::println);


}


输出结果


yes


yes


no


no

[](

)flapMap


flatMap 接收一个 Function<T, R>函数接口: Stream flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);即入参为集合类型,返回 Stream 类型。


@Test


public void testFlatMap() {


String[] arr1 = {"a", "b"};


String[] arr2 = {"e", "f"};


String[] arr3 = {"h", "j"};


// Stream.of(arr1, arr2, arr3).flatMap(x -> Arrays.stream(x)).forEach(System.out::println);


Stream.of(arr1, arr2, arr3).flatMap(Arrays::stream).forEach(System.out::println);


}


输出结果


a


b


e


f


h


j

[](

)有状态


  • distinct:元素去重

  • sorted:元素排序

  • limit:获取前面的指定数量的元素

  • skip:跳过前面指定数量的元素,获取后面的元素

  • concat:把两个 stream 合并成一个 stream

[](

)distinct


@Test


public void testDistinct() {


List<String> list = new ArrayList<String>() {


{


add("user1");


add("user2");


add("user2");


add("user2");


}


};


list.stream().distinct().forEach(System.out::println);


}


输出结果


user1


user2

[](

)sorted

[](

)sorted


@Test


public void testSorted1() {


String[] arr1 = {"abc", "a", "bc", "abcd"};


// 按照字符长度排序


System.out.println("lambda 表达式");


Arrays.stream(arr1).sorted((x, y) -> {


if (x.length() > y.length())


return 1;


else if (x.length() < y.length())


return -1;


else


return 0;


}).forEach(System.out::println);


// Comparator.comparing 是一个键提取的功能


System.out.println("方法引用");


Arrays.stream(arr1).sorted(Comparator.comparing(String::length)).forEach(System.out::println);


}


输出结果


lambda 表达式


a


bc


abc


abcd


方法引用


a


bc


abc


abcd

[](

)reversed


/**


  • 倒序

  • reversed(),java8 泛型推导的问题,所以如果 comparing 里面是非方法引用的 lambda 表达式就没办法直接使用 reversed()

  • Comparator.reverseOrder():也是用于翻转顺序,用于比较对象(Stream 里面的类型必须是可比较的)

  • Comparator.naturalOrder():返回一个自然排序比较器,用于比较对象(Stream 里面的类型必须是可比较的)


*/


@Test


public void testSorted2_() {


String[] arr1 = {"abc", "a", "bc", "abcd"};


System.out.println("reversed(),这里是按照字符串长度倒序排序");


Arrays.stream(arr1).sorted(Comparator.comparing(String::length).reversed()).forEach(System.out::println);


System.out.println("Comparator.reverseOrder(),这里是按照首字母倒序排序");


Arrays.stream(arr1).sorted(Comparator.reverseOrder()).forEach(System.out::println);


System.out.println("Comparator.naturalOrder(),这里是按照首字母顺序排序");


Arrays.stream(arr1).sorted(Comparator.naturalOrder()).forEach(System.out::println);


}


输出结果


reversed(),这里是按照字符串长度倒序排序


abcd


abc


bc


a


Comparator.reverseOrder(),这里是按照首字母倒序排序


bc


abcd


abc


a


Comparator.naturalOrder(),这里是按照首字母顺序排序


a


abc


abcd


bc

[](

)thenComparing


/**


  • thenComparing

  • 先按照首字母排序

  • 之后按照 String 的长度排序


*/


@Test


public void testSorted3() {


String[] arr1 = {"abc", "a", "bc", "abcd"};


Arrays.stream(arr1).sorted(Comparator.comparing(this::firstChar).thenComparing(String::length)).forEach(System.out::println);


}


public char firstChar(String x) {


return x.charAt(0);


}


输出结果


a


abc


abcd


bc

[](

)limit


/**


  • limit,限制从流中获得前 n 个数据


*/


@Test


public void testLimit() {


Stream.iterate(1, x -> x + 2).limit(3).forEach(System.out::println);


}


输出结果


1


3


5

[](

)skip


/**


  • skip,跳过前 n 个数据


*/


@Test


public void testSkip() {


Stream.iterate(1, x -> x + 2).skip(1).limit(3).forEach(System.out::println);


}


输出结果


3


5


7

[](

)concat


/**


  • 可以把两个 stream 合并成一个 stream(合并的 stream 类型必须相同)

  • 只能两两合并


*/


@Test


public void testConcat(){


// 1,3,5


Stream<Integer> stream1 = Stream.iterate(1, x -> x + 2).limit(3);


// 3,5,7


Stream<Integer> stream2 = Stream.iterate(1, x -> x + 2).skip(1).limit(3);


Stream.concat(stream1,stream2).distinct().forEach(System.out::println);


}


输出结果


1


3


5


7


[](


)终结操作



[](

)非短路操作


  • forEach:遍历

  • toArray:将流转换为 Object 数组

  • reduce : 归约,可以将流中的元素反复结合起来,得到一个值

  • collect:收集,将流装换为其他形式,比如 List,Set,Map

  • max:返回流的最大值,无方法参数

  • min:返回流中的最小值,无方法参数

  • count:返回流中的元素总个数,无方法参数

  • summaryStatistics:获取汇总统计数据,比如最大值,最小值,平均值等

[](

)forEach


@Test


public void testForEach() {


List<String> list = new ArrayList<String>() {


{


add("a");


add("b");


}


};


list.stream().forEach(System.out::println);


}


输出结果


a


b

[](

)reduce


@Test


public void testReduce() {


Optional<Integer> optional = Stream.of(1, 2, 3).filter(x -> x > 1).reduce((x, y) -> x + y);


System.out.println(optional.get());


}


输出结果


5

[](

)collect


收集是非常常用的一个操作。 将流装换为其他形式。接收到一个 Collector 接口的实现,用于给 Stream 中的元素汇总的方法。用 collect 方法进行收集。方法参数为 Collector。Collector 可以由 Collectors 中的 toList(),toSet(),toMap(Function(T,R) key,Function(T,R) value)等静态方法实现。


  • toList() 返回一个 Collector,它将输入元素到一个新的 List 。

  • toSet() 返回一个 Collector,将输入元素到一个新的 Set 。

  • toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper) 返回一个 Collector ,它将元素累加到一个 Map ,其键和值是将所提供的映射函数应用于输入元素的结果。


用户


@Data


@AllArgsConstructor


@ToString


public class User {


private String name;


private Integer age;


private Integer salary;


}

[](

)toList,toSet,toSet


@Test


public void testCollect() {


List<User> users = Arrays.asList(new User("张三", 19, 1000),


new User("张三", 58, 2000),


new User("李四", 38, 3000),


new User("赵五", 48, 4000)


);


List<String> collect = users.stream().map(x -> x.getName()).collect(Collectors.toList());


Set<String> collect1 = users.stream().map(x -> x.getName()).collect(Collectors.toSet());


Map<Integer, String> collect2 = users.stream().collect(Collectors.toMap(x -> x.getAge(), x -> x.getName()));


System.out.println(collect);


System.out.println(collect1);


System.out.println(collect2);


}


输出结果


[张三, 张三, 李四, 赵五]


[李四, 张三, 赵五]


{48=赵五, 19=张三, 38=李四, 58=张三}

[](

)groupingBy


Collectors.groupingBy()方法根据分类功能分组元素。这个是非常常用的操作。 比如你要对名字相同的进行分组。groupingBy(Function<? super T,? extends K> classifier)


@Test


public void testGroupby() {


List<User> users = Arrays.asList(new User("张三", 19, 1000),


new User("张三", 58, 2000),


new User("李四", 38, 3000),


new User("赵五", 48, 4000)


);


Map<String, List<User>> collect3 = users.stream().collect(Collectors.groupingBy(x -> x.getName()));


System.out.println(collect3);


}


输出结果


{李四=[StreamTest.User(name=李四, age=38, salary=3000)], 张三=[StreamTest.User(name=张三, age=19, salary=1000), StreamTest.User(name=张三, age=58, salary=2000)], 赵五=[StreamTest.User(name=赵五, age=48, salary=4000)]}

[](

)partitioningBy


如果只有两类,使用 partitioningBy 会比 groupingBy 更有效率,按照工资是否大于 2500 分组


@Test


public void testPartitioningBy() {


List<User> users = Arrays.asList(new User("张三", 19, 1000),


new User("张三", 58, 2000),


new User("李四", 38, 3000),


new User("赵五", 48, 4000)


);


Map<Boolean, List<User>> map = users.stream().collect(Collectors.partitioningBy(x -> x.getSalary() > 2500));


map.forEach((x, y) -> System.out.println(x + "->" + y));


}


输出结果


false->[StreamTest.User(name=张三, age=19, salary=1000), StreamTest.User(name=张三, age=58, salary=2000)]


true->[StreamTest.User(name=李四, age=38, salary=3000), StreamTest.User(name=赵五, age=48, salary=4000)]

[](

)max、min


@Test


public void testMaxAndMin() {


String[] arr = new String[]{"b", "ab", "abc", "abcd", "abcde"};


Stream.of(arr).max(Comparator.comparing(String::length)).ifPresent(System.out::println);


Stream.of(arr).min(Comparator.comparing(String::length)).ifPresent(System.out::println);


}


输出结果


abcde


b

[](

)count


@Test


public void testCount(){


String[] arr = new String[]{"b", "ab", "abc", "abcd", "abcde"};


long count = Stream.of(arr).count();


System.out.println(count);


}


输出结果


5

[](

)summaryStatistics


我们可以使用 summaryStatistics 方法获得 stream 中元素的各种汇总数据


@Test


public void testSummaryStatistics() {


//计算 count, min, max, sum, and average for numbers


List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);


// IntSummaryStatistics stats = numbers.stream().collect(Collectors.summarizingInt(x -> x));


IntSummaryStatistics stats = numbers


.stream()


.mapToInt(x -> x)


.summaryStatistics();


System.out.println("List 中最大的数字 : " + stats.getMax());


System.out.println("List 中最小的数字 : " + stats.getMin());


System.out.println("所有数字的总和 : " + stats.getSum());


System.out.println("所有数字的平均值 : " + stats.getAverage());


}


输出结果


List 中最大的数字 : 10


List 中最小的数字 : 1


所有数字的总和 : 55


所有数字的平均值 : 5.5

[](

)短路操作


  • anyMatch:检查是否有一个元素匹配,方法参数为断言型接口

  • allMatch:检查是否匹配所有元素,方法参数为断言型接口

  • findFirst:返回第一个元素,无方法参数

  • findAny:返回当前流的任意元素,无方法参数

  • noneMatch:检查是否没有匹配所有元素,方法参数为断言型接口

[](

)anyMatch


@Test


public void testAnyMatch() {


String[] arr = new String[]{"b", "ab", "abc", "abcd", "abcde"};


Boolean aBoolean = Stream.of(arr).anyMatch(x -> x.startsWith("a"));


System.out.println(aBoolean);


}


输出结果


true

[](

)findFirst


@Test


public void testFindFirst() {


String[] arr = new String[]{"b", "ab", "abc", "abcd", "abcde"};


String str = Stream.of(arr).parallel().filter(x -> x.length() > 3).findFirst().orElse("noghing");


System.out.println(str);


}


输出结果


abcd

[](

)findAny


/**


  • findAny

  • 找到所有匹配的元素

  • 对并行流十分有效

  • 只要在任何片段发现了第一个匹配元素就会结束整个运算


*/


@Test


public void testFindAny() {


String[] arr = new String[]{"b", "ab", "abc", "abcd", "abcde"};


Optional<String> optional = Stream.of(arr).parallel().filter(x -> x.length() > 2).findAny();


optional.ifPresent(System.out::println);


}


输出结果


abc

[](

)Optional 类型


通常聚合操作会返回一个 Optional 类型,Optional 表示一个安全的指定结果类型,所谓的安全指的是避免直接调用返回类型的 null 值而造成空指针异常,调用 optional.ifPresent()可以判断返回值是否为空,或者直接调用 ifPresent(Consumer<? super T> consumer)在结果不为


【一线大厂Java面试题解析+核心总结学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


空时进行消费操作;调用 optional.get()获取返回值。通常的使用方式如下:


@Test


public void testOptional() {


List<String> list = new ArrayList<String>() {


{


add("user1");


add("user2");


}


};


Optional<String> opt = Optional.of("user3");


opt.ifPresent(list::add);


list.forEach(System.out::println);


}


输出结果

用户头像

极客good

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
Java8新特性-Stream,java数据结构和算法pdf百度云