Java------Stream流式编程高级API【mapTo、Collectors】(五)

Java------Stream流式编程高级API【mapTo、Collectors、groupingBy、flatMap】(五)

mapTo,折叠操作

折叠操作又称为规约操作,是从一系列输入元素中,通过组合操作组成单个摘要结果。比如:查找一组数字的和、最大值、最小值、个数等。
常用的折叠操作:
max()、min()、count()、sum()、groupby()、groupby()+max()。
以上为了方便对纯数字的流进行处理。
提供了三种基本类型的Stream
IntStream、DoubleStream、LongStream。
通过Stream接口中的三个方法可以得到这三个对象。

IntStream mapToInt(ToIntFunction<? super T> mapper);
//ToIntFunction函数式接口,放lamba表达式
@FunctionalInterface
public interface ToIntFunction<T> {

    /**
     * Applies this function to the given argument.
     *
     * @param value the function argument
     * @return the function result
     */
    int applyAsInt(T value);
}

LongStream mapToLong(ToLongFunction<? super T> mapper);
DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper);

示例一:得到数字流,求最大、最小

    @Test
    public void test1() {
        int[] intArr = new int[]{1,2,3,4,5,1,2};
        IntStream stream = Arrays.stream(intArr);
        //求个数
        long count = stream.count();
        System.out.println(count);
        //求最大值
        OptionalInt max = Arrays.stream(intArr).max();
//        int asInt = stream.max().getAsInt();
        //直接输出max会报错,
        System.out.println(max);
//        System.out.println(asInt);
        //求最小值 会报错, stream has already been operated upon or closed
        OptionalInt min = stream.min();
        System.out.println(min);
    }

其中调用max值时,返回的类型是OptionalInt,打印输出的结果时:OptionalInt[5],如果想获取它的value。则需要调用getAsInt()方法。

OptionalInt max = Arrays.stream(intArr).max();

根据源码:如果没有值的话,会抛出异常,有值,则返回value

    public int getAsInt() {
        if (!isPresent) {
            throw new NoSuchElementException("No value present");
        }
        return value;
    }

而流直接调用max方法,也会抛出异常,stream has already been operated upon or closed。此时需要新建一个流

OptionalInt min = stream.min();
Arrays.stream(intArr).min();

案例二:List数组、map进行数字流处理

        @Test
    public void test1() {
        Map<String,Integer> map = new HashMap<>();
        map.put("a",1);
        map.put("b",2);
        map.put("c",3);
        map.put("d",4);
        map.put("e",5);
        Stream<Map<String, Integer>> map1 = Stream.of(map);
        long a = map1.mapToInt(x -> x.get("a")).count();
        //1
        System.out.println(a);

        List<Studengt> list = new ArrayList<>();
        list.add(new Studengt("aa",1));
        list.add(new Studengt("bb",2));
        list.add(new Studengt("cc",9));
        OptionalInt max = list.stream().mapToInt(x -> x.getAge()).max();
        //9
        System.out.println(max.getAsInt());
    }

Collectors 实现将流转list、set、map

使用Collectors收集器,实现对流进行可变的折叠操作。将流转成List、Set、Map。
在Stream接口中有一个collect方法收集器进行操作
collect源码

<R, A> R collect(Collector<? super T, A, R> collector);

Collector源码

public interface Collector<T, A, R> {

如何得到收集器对象?在收集器中制定了转换list、map、set的方法。
在collectors中定义了很多收集器创建方法,toList实现转list、toSet转set,toMap转map。
1.创建流对象
2.创建收集器对象
3.执行stream流对象的collection方法,进行收集,转成List、set、Map。

案例三:stream转List。

        String[] strArr = new String[]{"a","bb","ccc","dddd"};
        //默认返回arrylist
        List<String> collect = Arrays.stream(strArr).collect(Collectors.toList());
        collect.stream().forEach(System.out::println);
        //指定linkList,LinkedList::new构造方法引用
        LinkedList<String> collect1 = Arrays.stream(strArr).collect(Collectors.toCollection(LinkedList::new));

案例四:基本类型数组转流对象

int数组调用stream方法,返回的时IntStream对象,这样的对象时无法调用。

        int[] intArr = new int[]{1,22,333,4444,55555};
        //语句报错无法执行
        Arrays.stream(intArr).collect(Collectors.toList());

此时调用的collect方法时,另一个需要传入三个参数的方法。

<R> R collect(Supplier<R> supplier,
                  ObjIntConsumer<R> accumulator,
                  BiConsumer<R, R> combiner);

如果想要正常转List,则需要调用.stream().boxed()方法。
.boxed():将流中的元素进行装箱,将基本类型的数组转成含有包装类的流。

如代码所示

int[] intArr = new int[]{1,22,333,4444,55555};
        //语句报错无法执行
        List<Integer> collect1 = Arrays.stream(intArr).boxed().collect(Collectors.toList());

案例五:list转Map,方法一样,但是map需要指定key、和value,转为年龄为key,Student对象为value的Map

        List<Studengt> list = new ArrayList<>();
        list.add(new Studengt("aa",1));
        list.add(new Studengt("bb",2));
        list.add(new Studengt("cc",9));
        Map<Integer, Studengt> collect1 = list.stream().collect(Collectors.toMap(x -> x.getAge(), x -> x));

map中key唯一,当使用合并流,流转map时,如果指定的key一样,则会报错,但也有解决办法

        List<Studengt> list = new ArrayList<>();
        list.add(new Studengt("aa",1));
        list.add(new Studengt("bb",2));
        list.add(new Studengt("cc",9));
        List<Studengt> list2 = new ArrayList<>();
        list2.add(new Studengt("aa",1));
        list2.add(new Studengt("bbc",8));
        list2.add(new Studengt("ddd",9));
        Stream.concat(list.stream(),list2.stream()).collect(Collectors.toMap(x->x.getAge(),x->x));

两个map的key冲突时,解决办法:指定冲突时,使用哪一个value。

List<Studengt> list = new ArrayList<>();
        list.add(new Studengt("aa",1));
        list.add(new Studengt("bb",2));
        list.add(new Studengt("cc",9));
        List<Studengt> list2 = new ArrayList<>();
        list2.add(new Studengt("aa",1));
        list2.add(new Studengt("bbc",8));
        list2.add(new Studengt("ddd",9));
Map<Integer, Studengt> collect = Stream.concat(list.stream(), list2.stream()).collect(Collectors.toMap((x) -> x.getAge(), x -> x, (x1, x2) -> x1));
        collect.forEach((key,va)-> System.out.println(key+"+++++"+va));
        //输出结果
1+++++Studengt{name='aa', age=1}
2+++++Studengt{name='bb', age=2}
8+++++Studengt{name='bbc', age=8}
9+++++Studengt{name='cc', age=9}

默认是HashMap类型,如何指定为TreeMap类型?
与List指定LinkList一样,传入构造方法的引用,此时是自然排序

Map<Integer, Studengt> collect = Stream.concat(list.stream(), list2.stream()).collect(Collectors.toMap((x) -> x.getAge(), x -> x, (x1, x2) -> x1, TreeMap::new));

如何指定为TreeMap类型,指定排序,不用自然排序?

Supplier<TreeMap<Integer,Studengt>> treeMapSupplier = ()->new TreeMap<>(Comparator.reverseOrder());
        Map<Integer, Studengt> collect = Stream.concat(list.stream(), list2.stream()).collect(Collectors.toMap((x) -> x.getAge(), x -> x, (x1, x2) -> x1, treeMapSupplier));
        collect.forEach((key,va)-> System.out.println(key+"+++++"+va));

List转Set

如果使用TreeSet,则元素需要实现Compare接口
实体类改造:

public class Studengt implements Comparable<Studengt>{
@Override
    public int compareTo(Studengt o) {
        return this.getAge()-o.getAge();
    }
  

示例六List转Set

        System.out.println("===========hashSet=============");
        //转set,默认hashset
        Set<Studengt> collect = concat.collect(Collectors.toSet());
        collect.forEach(System.out::println);
        System.out.println("===========TreeSet,默认排序=============");
        //转TreeSet
        TreeSet<Studengt> collect2 = Stream.concat(list.stream(), list2.stream()).collect(Collectors.toCollection(TreeSet::new));
        collect2.forEach(System.out::println);
        System.out.println("===========TreeSet,age降序排序=============");
        //转TreeSet,并且指定age降序排序
        Supplier<TreeSet<Studengt>> treeSetSupplier = ()->new TreeSet<>((o1,o2)->(int)(o2.getAge()-o1.getAge()));
        TreeSet<Studengt> collect3 = Stream.concat(list.stream(), list2.stream()).collect(Collectors.toCollection(treeSetSupplier));
        collect3.forEach(System.out::println);
    }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
java stream Collectors.toMap是一个式处理方法,用于将一个List集合转换为Map集合。它接受三个参数:第一个参数指定了作为Map的key值的属性或方法引用,第二个参数指定了作为Map的value值的属性或方法引用,第三个参数用于处理key重复的情况。 通过使用Collectors.toMap方法,可以将一个List集合中的元素按照指定的属性或方法引用作为key值,将整个对象或属性值作为value值,构建出一个key值唯一的Map集合。 举例来说,如果有一个List<proVo>对象的集合,我们希望将其中的proVo对象按照id作为key,name作为value,构建成一个Map集合,可以使用如下代码: Map<Long, String> map = list.stream().collect(Collectors.toMap(proVo::getId, proVo::getName)); 这样就可以得到一个key为id,value为name的Map集合。 另外,如果在转换过程中遇到了key重复的情况,可以通过第三个参数来处理。比如可以选择保留前一个元素的值,或者保留后一个元素的值,或者进行其他自定义的处理。 例如: Map<Long, String> map = list.stream().collect(Collectors.toMap(proVo::getId, proVo::getName, (k1, k2) -> k1)); 这样当遇到key重复的情况时,会保留前一个元素的值作为value。 总之,java stream Collectors.toMap方法是用于将List集合转换为Map集合的一个便捷方法,可以根据需求选择合适的参数来进行处理。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [java8stream源码-streams:用于针对旧设备的Android项目的java.util.stream库的非常不完整的重新实现](https://download.csdn.net/download/weixin_38690522/19389466)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [【业务功能篇35】Java Stream :Collectors.toMap](https://blog.csdn.net/studyday1/article/details/131454535)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值