「java8」阿里架构师:Stream对集合的处理方式你全都知道了吗?

发布一下 0 0

一、概述


Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。


特点:


  • 元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
  • 数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。
  • 聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。
  • Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。
  • 内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。


二、Stream的创建


Stream可以通过集合数组创建。


1、通过 java.util.Collection.stream() 方法用集合创建流


List<Integer> list = Arrays.asList(1, 2, 3);// 创建一个顺序流Stream<Integer> stream = list.stream();// 创建一个并行流Stream<Integer> parallelStream = list.parallelStream();


2、使用java.util.Arrays.stream(T[] array)方法用数组创建流


int[] array={1,3,5,6,8};IntStream stream = Arrays.stream(array);


3、使用Stream的静态方法:of()、iterate()、generate()(我不是很常用)


Stream<Integer> stream = Stream.of(1, 2, 3);// of内部的方法,等同于使用数组创建流@SafeVarargs@SuppressWarnings("varargs") // Creating a stream from an array is safepublic static<T> Stream<T> of(T... values) {    return Arrays.stream(values);}Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 3).limit(4);stream2.forEach(System.out::print);System.out.println();Stream<Double> stream3 = Stream.generate(Math::random).limit(3);stream3.forEach(System.out::println);


输出结果:


03690.49189549200548930.82466382643695550.17880449237798712


将对象集合转成对象中某个属性的集合


List<ReviewerRest> list = new ArrayList<>();List<Long> ids = list.stream().map(ReviewerRest::getId).collect(Collectors.toList());复制代码


将某个属性的集合转成对象集合


List<Long> ids = new ArrayList<>();List<ReviewerRest> list = ids.stream().map(id -> {  ReviewerRest rest = new ReviewerRest();  rest.setRest(1);  rest.setDate(LocalDate.now());  rest.setReviewerId(1000L);  return rest;}).collect(Collectors.toList());复制代码


判断集合中是否有一个对象包含某个属性


boolean exist = list.stream().anyMatch(rest -> rest.getReviewerId().equals(1000L));//...... allMatch 和 anyMatch 类似复制代码


对集合中某个对象的属性求和


BigDecimal reduce = list.stream().map(ReviewerRest::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add);复制代码


集合转 Map (普通)


Map<Long, ReviewerRest> map = list.stream().collect(Collectors.toMap(ReviewerRest::getId, x -> x));复制代码


集合转 Map (key 存在重复)


当集合中 id 会存在重复时,上面那种方式会报错,此时需要指定重复时选用哪一个 value


Map<Long, ReviewerRest> map = list.stream().collect(Collectors.toMap(ReviewerRest::getId, x -> x, (before, after) -> after));复制代码


集合转 Map (value 存在 null 值)


当 value 存在 null 值时上面那种方式会报错,此时需要换一种写法


Map<Long, LocalDate> map = list.stream().collect(HashMap::new, (mapItem, item) -> mapItem.put(item.getId(), item.getDate()), HashMap::putAll);复制代码


集合分组 转 Map


Map<Long, List<ReviewerRest>> map = list.stream().collect(Collectors.groupingBy(ReviewerRest::getId));复制代码


集合分区 转 Map


Map<Boolean, List<ReviewerRest>> map = list.stream().collect(Collectors.partitioningBy(r -> r.getRest() == 1));复制代码


集合分组个数统计


Map<Long, Long> map = list.stream().collect(Collectors.groupingBy(ReviewerRest::getId,Collectors.counting()));复制代码


集合分组转某个属性集合


Map<Long, List<Integer>> map = list.stream().collect(Collectors.groupingBy(ReviewerRest::getId,Collectors.mapping(ReviewerRest::getRest,Collectors.toList())));复制代码


集合分组聚合查询最大元素


Map<Long, Optional<ReviewerRest>> map = list.stream().collect(Collectors.groupingBy(ReviewerRest::getReviewerId, Collectors.maxBy(Comparator.comparing(ReviewerRest::getDate))));复制代码


集合分组聚合求和


//目前只支持 int、double、longMap<Long, Long> map = list.stream().collect(Collectors.groupingBy(ReviewerRest::getReviewerId, Collectors.summingLong(


java8采用stream对集合的常用操作


User :{	id,	name,	age}


1.对象集合的分组(有两种形式)
示例:List userList,根据id分组,可以分组成为两种格式的map
(1)Map<id,User>


Map<id,User> map = userList.stream().collect(Collectors.toMap(User::getId, Function.identity()));


(2)Map<id,List>


Map<id,List<User>> = userList.stream().collect(Collectors.groupingBy(User::getId));


2.去重操作
对List 实现去重,distinct关键字


示例:userList= userList.stream().distinct().collect(Collectors.toList());


3.stream的map
主要用于得到特定的结构
例如:List userList,我向得到User Id的集合


List<Integer> idList = userList.stream.map(User::getId).collect(Collectors.toList());


4.stream的filter
主要用于数据的筛选。
例1:一个条件的筛选,删选id>5的User


List<UserList> userList = userList.stream.filter(i->i.getId()>5).collect(Collectors.toList());


例2:两个条件的删选用&&连接就行,删选id>5年纪>10的User


List<UserList> userList = userList.stream.filter(i->i.getId()>5&&i.getAge()>10).collect(Collectors.toList());


5.用来作循环


userList.stream().forEach(user -> System.out.println("姓名:" + user.getName())); 


当然也可以加个limit限制数量


userList.stream().limit(2).forEach(user -> System.out.println("姓名:" + user.getName())); 


6.最大值最小值


 int maxAge = userList.stream().mapToInt(User::getAge).max().getAsInt(); int minAge = userList.stream().mapToInt(User::getAge).min().getAsInt();


封装的Stream使用类,可以直接拿走使用:


public class StreamUtils {    /**     * 集合为空,创建空的Stream流;否则创建集合的Stream流     * 避免出现空指针     *     * @param collection 集合     * @param <T>   集合元素的泛型     * @return Stream对象     */    private static <T> Stream<T> streamOf(Collection<T> collection) {        return CollectionUtils.isEmpty(collection) ? Stream.empty() : collection.stream();    }    /**     * 按照映射规则映射成一个新的集合流     *     * @param list  集合     * @param mapper   集合属性元素     * @param <T>   函数输入类型的泛型     * @param <R>   函数结果类型的泛型     * @return  新的集合     */    public static <T, R> List<R> mapList(List<T> list, Function<? super T, ? extends R> mapper) {        return streamOf(list).map(mapper).collect(Collectors.toList());    }    /**     * 根据给定的条件进行筛选,将符合条件的元素提取成新的流     *     * @param list          集合     * @param predicate     筛选规则     * @param <T>           流元素的类型     * @return  符合条件的流集合     */    public static <T> List<T> filter(List<T> list, Predicate<? super T> predicate) {        return streamOf(list).filter(predicate).collect(Collectors.toList());    }    /**     * 根据给定的条件进行筛选,将符合条件的元素提取成新的流     *     * @param list          集合     * @param predicates    多个筛选条件     * @param <T>           流元素的类型     * @return 符合条件的流集合     */    @SafeVarargs    public static <T> List<T> filters(List<T> list, Predicate<? super T> ... predicates) {        Stream<T> stream = streamOf(list);        for (Predicate<? super T> predicate : predicates) {            stream = stream.filter(predicate);        }        return stream.collect(Collectors.toList());    }    /**     * 根据指定元素对集合进行升序排序     *     * @param list  集合     * @param keyExtractor  用来排序的元素     * @param <T>   函数输入类型的泛型     * @param <U>   函数结果类型的泛型     * @return  排序后的集合     */    public static <T, U extends Comparable<? super U>> List<T> sorted(            List<T> list, Function<? super T, ? extends U> keyExtractor) {        return streamOf(list).sorted(Comparator.comparing(keyExtractor)).collect(Collectors.toList());    }    /**     * 根据指定元素对集合进行升序排序     *     * @param list  集合     * @param keyExtractor  用来排序的元素     * @param limit     排序后集合中保留的数量     * @param <T>   函数输入类型的泛型     * @param <U>   函数结果类型的泛型     * @return  排序后的集合     */    public static <T, U extends Comparable<? super U>> List<T> sorted(            List<T> list, Function<? super T, ? extends U> keyExtractor, Integer limit) {        return streamOf(list).sorted(Comparator.comparing(keyExtractor)).limit(limit).collect(Collectors.toList());    }    /**     * 根据指定元素对集合进行降序排序     *     * @param list  集合     * @param keyExtractor  用来排序的元素     * @param <T>   函数输入类型的泛型     * @param <U>   函数结果类型的泛型     * @return  排序后的集合     */    public static <T, U extends Comparable<? super U>> List<T> sortedDesc(            List<T> list, Function<? super T, ? extends U> keyExtractor) {        return streamOf(list).sorted(Comparator.comparing(keyExtractor).reversed()).collect(Collectors.toList());    }    /**     *根据规则判断元素是否匹配     *     * @param list  集合     * @param predicate 匹配规则     * @param <T>   元素类型     * @return  匹配结果     */    public static <T> boolean anyMatch(List<T> list, Predicate<? super T> predicate) {        return streamOf(list).anyMatch(predicate);    }    /**     * 将List集合转换成Map集合,同一个key时对value进行去重,保留第一个出现的value值     *     * @param list  集合     * @param keyMapper     新的Map中的key     * @param <T>   参数的类型     * @return  转换后的Map集合   <key, T>     */    public static <T, K> Map< K, T> toMapDistinctFirst(List<T> list, Function<? super T, ? extends K> keyMapper) {        return streamOf(list).collect(Collectors.toMap(keyMapper, Function.identity(), (key1, key2) -> key1));    }    /**     * 将List集合转换成Map集合,同一个key时对value进行去重,保留最后出现的value值     *     * @param list  集合     * @param keyMapper     新的Map中的key     * @param <T>   参数的类型     * @return  转换后的Map集合   <key, T>     */    public static <T, K> Map<K, T> toMapDistinctLast(List<T> list, Function<? super T, ? extends K> keyMapper) {        return streamOf(list).collect(Collectors.toMap(keyMapper, Function.identity(), (key1, key2) -> key2));    }    /**     * 将List转换为指定key->value键值对元素的Map集合     * @param list  集合     * @param keyMapper     Map的key元素     * @param valueMapper   Map的value元素     * @param <T>   函数输入的类型     * @param <K>   函数输出的类型     * @param <U>   函数输出的类型     * @return  转换后的Map集合   <key, value>     */    public static <T, K, U> Map<K, U> toMap(List<T> list, Function<? super T, ? extends K> keyMapper,                            Function<? super T, ? extends U> valueMapper) {        return streamOf(list).collect(Collectors.toMap(keyMapper, valueMapper));    }}

最后希望大家能从文章中得到帮助获得收获,也可以评论出你想看哪方面的技术。文章会持续更新,希望能帮助到大家,哪怕是让你灵光一现。喜欢的朋友可以点点赞和关注,也可以分享出去让更多的人看见,一起努力一起进步!



版权声明:内容来源于互联网和用户投稿 如有侵权请联系删除

本文地址:http://0561fc.cn/170504.html