Collectors和Collector

一。Collector是一个接口,位于java.util.stream包下。

汉翻:集合,收集的意思

1.1。Collector有以下方法。

public interface Collector<T, A, R> {
    /* supplier参数用于生成结果容器,容器类型为A*/
    Supplier<A> supplier();

    /**accumulator用于消费元素,也就是归纳元素,这里的T就是元素,它会将流中的元素一个一个与结果容器A发生操作
     */
    BiConsumer<A, T> accumulator();

    /**combiner用于两个两个合并并行执行的线程的执行结果,将其合并为一个最终结果A */
    BinaryOperator<A> combiner();

    /**
    // finisher用于将之前整合完的结果R转换成为A
     */
    Function<A, R> finisher();

// characteristics表示当前Collector的特征值,这是个不可变Set
    Set<Characteristics> characteristics();

}

1.2。Collector的of方法。

Collector接口中还有两个of方法用于生成Collector实例,其中一个拥有上面所有五个参数,另一个四个参数,不包括Function接口。

of方法,都是用于生成Collector实例,但四个参数返回值<T,R>,五个参数返回值<T,A,R>

T,代表流中一个一个元素,A代表中间结果,R代表流的结束,最终结果

function接口,将A转换成R

1.2.1.四个参数的of方法

public static<T, R> Collector<T, R, R> of(Supplier<R> supplier,
                                          BiConsumer<R, T> accumulator,
                                          BinaryOperator<R> combiner,
                                          Characteristics... characteristics) {
    Objects.requireNonNull(supplier);
    Objects.requireNonNull(accumulator);
    Objects.requireNonNull(combiner);
    Objects.requireNonNull(characteristics);
    Set<Characteristics> cs = (characteristics.length == 0)
                              ? Collectors.CH_ID
                              : Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH,
                                                                       characteristics));
    return new Collectors.CollectorImpl<>(supplier, accumulator, combiner, cs);
}
 

1.2.2。五个参数的of方法 

public static<T, A, R> Collector<T, A, R> of(   Supplier<A> supplier,

                                                                        BiConsumer<A, T> accumulator,                                                                         BinaryOperator<A> combiner,                                                                         Function<A, R> finisher,                                                                         Characteristics... characteristics) { Objects.requireNonNull(supplier);

Objects.requireNonNull(accumulator);

Objects.requireNonNull(combiner);

Objects.requireNonNull(finisher);

Objects.requireNonNull(characteristics);

Set<Characteristics> cs = Collectors.CH_NOID;

if (characteristics.length > 0) { cs = EnumSet.noneOf(Characteristics.class);

Collections.addAll(cs, characteristics); cs = Collections.unmodifiableSet(cs); }

return new Collectors.CollectorImpl<>(supplier, accumulator, combiner, finisher, cs);

}

1.3。Collector接口里面的枚举值 

Collector接口中最后一个枚举,里面有三个值。of中四个参数必须有IDENTITY_FINISH枚举值。

enum Characteristics {
    /**
   多线程并行
     */
    CONCURRENT,

    /**
     无序
     */
    UNORDERED,

    /**
     无需转换结果
     */
    IDENTITY_FINISH
}

 二。Collectors是一个工具类。有以下方法

toCollection,toList,toSet,toMap
joining,mapping,collectingAndThen,counting,minBy/maxBy
summingInt/summingLong/summingDouble
averagingInt/averagingLong/averagingDouble,reducing
groupingBy,
partitioningBy,
summarizingInt/summarizingLong/summarizingDouble

 2.1。toCollection-转集合

将流中的元素全部放置到一个集合中返回,这里使用Collection,泛指多种集合

collect()里面就一个参数,在stream流中将对应的集合收集起来,并返回该集合。

LinkedList::new  类::方法; 引用类中的实例方法

toCollection(LinkedList:new)相当于

toCollection((LinkList里面的属性字段)->new LinkedList(LinkedList里面的属性字段))

list首先转换成stream流,然后调用收集方法,收集参数里面的集合。这个集合只要是LinkedList的属性都放到返回值里面。

List<String> list = new ArrayList<>();
list.add("张三");
list.add("李四");
list.add("王五");
list.stream().collect(Collectors.toCollection(LinkedList::new));

 返回值

List<String> collect=list.stream().collect(Collectors.toCollection
(LinkedList::new));

2.2。toList-转列表

将流中的元素放置到一个列表集合中去。这个列表默认为ArrayList。

List<String> list= list.stream().collect(Collectors.toList())

2.3。toSet

将流中的元素放置到一个无序集set中去。默认为HashSet。 

public class CollectorsTest {

        public static void toSetTest(List<String> list) {

        Set<String> ss = list.stream().collect(Collectors.toSet());

}

public static void main(String[] args) {

        List<String> list =         Arrays.asList("123","456","789","1101","212121121","asdaa","3e3e3e","2321eew");

        toSetTest(list);

}

 2.4。toMap

toMap方法是根据给定的键生成器和值生成器生成的键和值保存到一个map中返回,键和值的生成都依赖于元素,可以指定出现重复键时的处理方案和保存结果的map。

public final class Collectors {
    // 指定键和值的生成方式keyMapper和valueMapper
    public static <T, K, U>
        Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
                                        Function<? super T, ? extends U> valueMapper) {/*...*/}
    // 在上面方法的基础上增加了对键发生重复时处理方式的mergeFunction,比如上面的默认的处理方法就是抛出异常
    public static <T, K, U>
        Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
                                        Function<? super T, ? extends U> valueMapper,
                                        BinaryOperator<U> mergeFunction) {/*...*/}
    // 在第二个方法的基础上再添加了结果Map的生成方法。
    public static <T, K, U, M extends Map<K, U>>
        Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,
                                    Function<? super T, ? extends U> valueMapper,
                                    BinaryOperator<U> mergeFunction,
                                    Supplier<M> mapSupplier) {/*...*/}
}

2.5。joining

joining的目的是将流中的元素全部以字符序列的方式连接到一起,可以指定连接符,甚至是结果的前后缀。

public class CollectorsTest {
    public static void joiningTest(List<String> list){
        // 无参方法
        String s = list.stream().collect(Collectors.joining());
        System.out.println(s);
        // 指定连接符
        String ss = list.stream().collect(Collectors.joining("-"));
        System.out.println(ss);
        // 指定连接符和前后缀
        String sss = list.stream().collect(Collectors.joining("-","S","E"));
        System.out.println(sss);
    }
    public static void main(String[] args) {
        List<String> list = Arrays.asList("123","456","789","1101","212121121","asdaa","3e3e3e","2321eew");
        joiningTest(list);
    }
}

StringJoiner:这是一个字符串连接器,可以定义连接符和前后缀,正好适用于实现第三种joining方法。

2.6。mapping 

这个映射是首先对流中的每个元素进行映射,即类型转换,然后再将新元素以给定的Collector进行归纳,同样我也可以通过映射,提前对象中的具体属性

public class CollectorsTest {
    public static void mapingTest(List<String> list){
        List<Integer> ll = list.stream().limit(5).collect(Collectors.mapping(Integer::valueOf,Collectors.toList()));
    }
    public static void main(String[] args) {
        List<String> list = Arrays.asList("123","456","789","1101","212121121","asdaa","3e3e3e","2321eew");
        mapingTest(list);
    }
}

实例中截取字符串列表的前5个元素,将其分别转换为Integer类型,然后放到一个List中返回

2.7。collectingAndThen

该方法是在归纳动作结束之后,对归纳的结果进行再处理。

2.8。counting

该方法用于计数。

public class CollectorsTest {
    public static void countingTest(List<String> list){
        long size = list.stream().collect(Collectors.counting());
        System.out.println(size);
    }
    public static void main(String[] args) {
        List<String> list = Arrays.asList("123","456","789","1101","212121121","asdaa","3e3e3e","2321eew");
        countingTest(list);
    }
}

2.9。minBy/maxBy

生成一个用于获取最小/最大值的Optional结果的Collector。

list.stream().collect(Collectors.maxBy((a,b) -> a.length()-b.length()))

2.10。summingInt/summingLong/summingDouble

生成一个用于求元素和的Collector,首先通过给定的mapper将元素转换类型,然后再求和。

参数的作用就是将元素转换为指定的类型,最后结果与转换后类型一致。

public class CollectorsTest {
    public static void summingTest(List<String> list){
        int i = list.stream().limit(3).collect(Collectors.summingInt(Integer::valueOf));
        long l = list.stream().limit(3).collect(Collectors.summingLong(Long::valueOf));
        double d = list.stream().limit(3).collect(Collectors.summingDouble(Double::valueOf));
        System.out.println(i +"\n" +l + "\n" + d);
    }
    public static void main(String[] args) {
        List<String> list = Arrays.asList("123","456","789","1101","212121121","asdaa","3e3e3e","2321eew");
        summingTest(list);
    }
}

2.11。averagingInt/averagingLong/averagingDouble

生成一个用于求元素平均值的Collector,首选通过参数将元素转换为指定的类型。

参数的作用就是将元素转换为指定的类型,求平均值涉及到除法操作,结果一律为Double类型。

public class CollectorsTest {
    public static void averagingTest(List<String> list){
        double i = list.stream().limit(3).collect(Collectors.averagingInt(Integer::valueOf));
        double l = list.stream().limit(3).collect(Collectors.averagingLong(Long::valueOf));
        double d = list.stream().limit(3).collect(Collectors.averagingDouble(Double::valueOf));
        System.out.println(i +"\n" +l + "\n" + d);
    }
    public static void main(String[] args) {
        List<String> list = Arrays.asList("123","456","789","1101","212121121","asdaa","3e3e3e","2321eew");
        averagingTest(list);
    }
}

2.12。reducing

reducing方法有三个重载方法,其实是和Stream里的三个reduce方法对应的,二者是可以替换使用的,作用完全一致,也是对流中的元素做统计归纳作用。

public final class Collectors {
    // 无初始值的情况,返回一个可以生成Optional结果的Collector
    public static <T> Collector<T, ?, Optional<T>> reducing(BinaryOperator<T> op) {/*...*/}
    // 有初始值的情况,返回一个可以直接产生结果的Collector
    public static <T> Collector<T, ?, T> reducing(T identity, BinaryOperator<T> op) {/*...*/}
    // 有初始值,还有针对元素的处理方案mapper,生成一个可以直接产生结果的Collector,元素在执行结果操作op之前需要先执行mapper进行元素转换操作
    public static <T, U> Collector<T, ?, U> reducing(U identity,
                                    Function<? super T, ? extends U> mapper,
                                    BinaryOperator<U> op) {/*...*/}
}

 2.13。groupingBy

这个方法是用于生成一个拥有分组功能的Collector,它也有三个重载方法:

public final class Collectors {
    // 只需一个分组参数classifier,内部自动将结果保存到一个map中,每个map的键为?类型(即classifier的结果类型),值为一个list,这个list中保存在属于这个组的元素。
    public static <T, K> Collector<T, ?, Map<K, List<T>>> groupingBy(
            Function<? super T, ? extends K> classifier) {/*...*/}
    // 在上面方法的基础上增加了对流中元素的处理方式的Collector,比如上面的默认的处理方法就是Collectors.toList()
    public static <T, K, A, D>Collector<T, ?, Map<K, D>> groupingBy(
            Function<? super T, ? extends K> classifier,Collector<? super T, A, D> downstream) {/*...*/}
    // 在第二个方法的基础上再添加了结果Map的生成方法。
    public static <T, K, D, A, M extends Map<K, D>>
        Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier,
                                      Supplier<M> mapFactory,
                                      Collector<? super T, A, D> downstream) {/*...*/}
}

当我们调用groupingBy方法时,

2.13.1.参数可以为一个

参数可以为一个,返回一个map,这个map的key为String类型,value是分组后的list集合

Collectors.groupingBy(String::length)

2.13.2.参数为二个的情况

参数为二个的情况,第一个参数同上,第二个参数可以加一个流中元素处理的工具类Collectors,把分组后的数据转换成list集合,set集合等等

Collectors.groupingBy(String::length, Collectors.toList())

2.13.3.参数为三个的情况

,中间参数再添加结果Map的生成方法

Collectors.groupingBy(String::length,HashMap::new,Collectors.toSet())

实例

public class CollectorsTest {
    public static void groupingByTest(List<String> list){
        Map<Integer,List<String>> s = list.stream().collect(Collectors.groupingBy(String::length));
        Map<Integer,List<String>> ss = list.stream().collect(Collectors.groupingBy(String::length, Collectors.toList()));
        Map<Integer,Set<String>> sss = list.stream().collect(Collectors.groupingBy(String::length,HashMap::new,Collectors.toSet()));
        System.out.println(s.toString() + "\n" + ss.toString() + "\n" + sss.toString());
    }
    public static void main(String[] args) {
        List<String> list = Arrays.asList("123","456","789","1101","212121121","asdaa","3e3e3e","2321eew");
        groupingByTest(list);
    }
}

2.14。partitioningBy

该方法将流中的元素按照给定的校验规则的结果分为两个部分,放到一个map中返回,map的键是Boolean类型,值为元素的列表List。

该方法有两个重载方法:

public final class Collectors {
    // 只需一个校验参数predicate
    public static <T>
        Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate) {/*...*/}
    // 在上面方法的基础上增加了对流中元素的处理方式的Collector,比如上面的默认的处理方法就是Collectors.toList()
    public static <T, D, A>
        Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate,
                                                        Collector<? super T, A, D> downstream) {/*...*/}
}

2.15。summarizingInt/summarizingLong/summarizingDouble

这三个方法适用于汇总的,返回值分别是IntSummaryStatistics,LongSummaryStatistics,DoubleSummaryStatistics。

在这些返回值中包含有流中元素的指定结果的数量、和、最大值、最小值、平均值。所有仅仅针对数值结果。

public class CollectorsTest {
    public static void summarizingTest(List<String> list){
        IntSummaryStatistics intSummary = list.stream().collect(Collectors.summarizingInt(String::length));
        LongSummaryStatistics longSummary = list.stream().limit(4).collect(Collectors.summarizingLong(Long::valueOf));
        DoubleSummaryStatistics doubleSummary = list.stream().limit(3).collect(Collectors.summarizingDouble(Double::valueOf));
        System.out.println(intSummary.toString() + "\n" + longSummary.toString() + "\n" + doubleSummary.toString());
    }
    public static void main(String[] args) {
        List<String> list = Arrays.asList("123","456","789","1101","212121121","asdaa","3e3e3e","2321eew");
        summarizingTest(list);
    }
}

整个Collectors工具类就是在为Collector服务,用于创建各种不同的Collector。部分功能与Stream中的方法重合了,为了简化代码,完全不必采用Collectors实现,优先Stream方法。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值