1 collect是什么 collect是对流(Stream)进行mutable reduction(可变缩减操作)操作的接口函数,已经有很多文章介绍collect多么牛逼,多么强大。对于初学Java的我这里只总结怎么用; 想了解更多的,可以查看以下链接。
签名:
有如下两个签名
<R> R collect (Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner) ; <R, A> R collect (Collector<? super T, A, R> collector) ;
2. Collector收集器 收集器(Collector)是为Stream.collect()方法量身打造的工具接口(类)。 考虑一下将一个Stream转换成一个容器(或者Map)需要做哪些工作?我们至少需要两样东西:
目标容器是什么?是ArrayList还是HashSet,或者是个TreeMap。
新元素如何添加到容器中?是List.add()还是Map.put()。
如果并行的进行规约,还需要告诉collect(),多个部分结果如何合并成一个。
结合以上分析,collect()方法定义为
<R > R collect(Supplier<R > supplier, BiConsumer<R ,? super T> accumulator, BiConsumer<R ,R > combiner),
三个参数依次对应上述三条分析。不过每次调用collect()都要传入这三个参数太麻烦,收集器Collector就是对这三个参数的简单封装, 所以collect()的另一定义为<R,A> R collect(Collector<? super T,A,R> collector)
。Collectors工具类可通过静态方法生成各种常用的Collector。
3. 具体使用 3.1 toList/toSet : 转成集合 List<Integer > integerList = Arrays.asList(1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ); // toList操作 List<Integer > collectList = integerList.stream().filter (integer -> integer % 3 == 0 ).collect(Collectors.toList());System .out .println("toList结果 -> " + collectList + ""); // 输出: toList结果 -> [3 , 6 , 9 ] // toSet操作Set <Integer > collectSet = integerList.stream().filter (integer -> integer % 2 == 0 ).collect(Collectors.toSet());System .out .println("toSet结果 -> " + collectSet + ""); // 输出: toSet结果 -> [2 , 4 , 6 , 8 ]
3.2 toCollection : 转换成特定的集合 List<Integer> integers = Arrays.asList(11 , 22 , 14 , 6 , 9 ); ArrayList<Integer> arrayList = integers.stream().collect(Collectors.toCollection(ArrayList::new )); System.out.println("toCollection 转ArrayList -> " + arrayList + "" ); HashSet<Integer> hashSet = integers.stream().collect(Collectors.toCollection(HashSet::new )); System.out.println("toCollection 转HashSet -> " + hashSet + "" ); TreeSet<Integer> treeSet = integers.stream().collect(Collectors.toCollection(TreeSet::new )); System.out.println("toCollection 转TreeSet -> " + treeSet + "" );
3.3 toMap : 转成map 1.结合实体类 public class Main { public static void main (String[] args) { List<Employee> employees = Arrays.asList( new Employee ("张三" , 18 ), new Employee ("李四" , 23 ), new Employee ("王麻子" , 30 ) ); Map<String, Integer> collect = employees.stream().collect(Collectors.toMap(Employee::getName, Employee::getAge)); System.out.println("toMap -> " + collect + "" ); } static class Employee { private String name; private int age; public Employee (String name, int age) { setName(name); setAge(age); } public String getName () { return name; } public void setName (String name) { this .name = name; } public int getAge () { return age; } public void setAge (int age) { this .age = age; } @Override public String toString () { StringBuilder str = null ; str = new StringBuilder (); str.append(" Name:- " + getName() + " Age:- " + getAge()); return str.toString(); } } }
2.集合直接转 List<Integer> integers = Arrays.asList(1 , 2 , 4 , 6 , 9 ); Map<Integer, String> collect = integers.stream().collect(Collectors.toMap(x -> x, x -> String.valueOf(x))); System.out.println("集合转toMap -> " + collect + "" );
3.4 averagingInt: 求平均值 List<Integer> integers = Arrays.asList (11 , 22 , 14 , 6 , 9 );Double collect = integers.stream().collect (Collectors.averagingInt(x -> x)); System.out.println ("平均值 -> " + collect + "" );
3.5 joining : 拼接 三种签名:
public static Collector<CharSequence,?,String> joining()public static Collector<CharSequence,?,String> joining(CharSequence delimiter)public static Collector<CharSequence,?,String> joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix)
代码
List<String> strings = Arrays.asList("php" , "is" , "the" , "best" ,"language" , "!" );String joining1 = strings.stream().collect(Collectors.joining()); System.out.println("第一种签名, 直接拼接 --> " + joining1 + " " );String joining2 = strings.stream().collect(Collectors.joining("|" )); System.out.println("第二种签名,带有分隔符拼接 --> " + joining2 + " " );String joining3 = strings.stream().collect(Collectors.joining("|" , "preFix_" , "_suffix" )); System.out.println("第三种签名,带有分隔符、前缀(preFix_)、后缀(_suffix)、拼接 --> " + joining3 + " " );
3.6 groupingBy : 分组 三种签名:
public static <T,K> Collector<T,?,Map<K,List<T>>> groupingBy(Function<? super T,? extends K > classifier)public static <T,K,A,D> Collector<T,?,Map<K,D>> groupingBy(Function<? super T,? extends K > classifier, Collector<? super T,A,D> downstream)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)
代码
employees 类
class Employee { private String name; private int age; private String sex; public Employee (String name, int age,String sex) { setName (name); setAge (age); setSex (sex); } public String getName ( ) { return name; } public void setName (String name ) { this .name = name; } public int getAge ( ) { return age; } public void setAge (int age ) { this .age = age; } public String getSex ( ) { return sex; } public void setSex (String age ) { this .sex = age; } @Override public String toString ( ) { StringBuilder str = null ; str = new StringBuilder (); str.append (" Name:- " + getName () + " Age:- " + getAge ()); return str.toString (); } }
List<Employee> employees = Arrays.asList ( new Employee("张颖" , 16 ,"女" ), new Employee("小英" , 25 ,"女" ), new Employee("王慧" , 22 ,"女" ), new Employee("李四" , 23 ,"男" ), new Employee("王麻子" , 27 ,"男" ) ); Map<String, List<Employee>> collect = employees.stream().collect (Collectors.groupingBy(Employee::getSex)); System.out.println ("根据性别分组 : \n " + collect + "\n" ); Map<Integer, List<Employee>> collect11 = employees.stream().collect (Collectors.groupingBy(Employee::getAge)); System.out.println ("根据年龄分组 : \n " + collect11 + "\n" );
List <Employee> employees = Arrays.asList( new Employee("张颖" , 16 ,"女" ), new Employee("小英" , 25 ,"女" ), new Employee("王慧" , 22 ,"女" ), new Employee("李四" , 23 ,"男" ), new Employee("王麻子" , 27 ,"男" ) );Map <String , Long> collect1 = employees.stream().collect(Collectors.groupingBy(Employee::getSex , Collectors.counting())); System.out.println("根据性别分组后,统计每组的count : \n " + collect1 + "\n" );Map <String , Double> collect2 = employees.stream().collect(Collectors.groupingBy(Employee::getSex , Collectors.averagingInt(Employee::getAge ))); System.out.println("根据性别分组后,计算每组的平均年龄: \n " + collect2 + "\n" );Map <String , Optional<Employee>> collect5 = employees.stream().collect(Collectors.groupingBy(Employee::getSex , Collectors.maxBy(Comparator.comparingInt(Employee::getAge )))); System.out.println("根据性别分组后,找出每组最大年龄 : \n " + collect5 + "\n" );Map <String , Map <Integer , List <Employee>>> collect3 = employees.stream().collect(Collectors.groupingBy(Employee::getSex , Collectors.groupingBy(Employee::getAge ))); System.out.println("根据性别、年龄分组: \n " + collect3 + "\n" );Map <String , Map <Integer , Long>> collect4 = employees.stream().collect(Collectors.groupingBy(Employee::getSex , Collectors.groupingBy(Employee::getAge , Collectors.counting()))); System.out.println("根据性别、年龄分组后,统计每组数量 : \n " + collect4 + "\n" );
List<Employee> employees = Arrays.asList( new Employee ("张颖" , 16 ,"女" ), new Employee ("小英" , 25 ,"女" ), new Employee ("王慧" , 22 ,"女" ), new Employee ("李四" , 23 ,"男" ), new Employee ("王麻子" , 27 ,"男" ) ); HashMap<String , List<Employee>> collect6 = employees.stream().collect(Collectors.groupingBy(Employee: :getSex, HashMap: :new , Collectors.toList())); System.out.println("根据性别分组并指定返回类型为HashMap : \n " + collect6 + "\n" ); HashMap<String , List<String >> collect7 = employees.stream().collect(Collectors.groupingBy(Employee: :getSex, HashMap: :new , Collectors.mapping(Employee: :getName, Collectors.toList()))); System.out.println("根据性别分组并、指定返回类型为HashMap,且分组中只显示成员姓名 : \n" + collect7 + "\n" );
3.7 partitioningBy : 分组 作用: 把数据分成两部分,key为ture/false。共有两种签名
签名
public static <T> Collector<T,?,Map<Boolean,List<T>>> partitioningBy(Predicate<? super T> predicate)public static <T,D,A> Collector<T,?,Map<Boolean,D>> partitioningBy(Predicate<? super T> predicate, Collector<? super T,A,D> downstream)
代码
List<Integer> integers = Arrays.asList(1 , 21 , 81 , 23 , 42 , 90 , 62 , 37 ); Map<Boolean, List<Integer>> collect = integers.stream().collect(Collectors.partitioningBy(x -> x % 2 ==0 )); System.out.println("能否被2整除,进行分组 -> " + collect + "" ); Map<Boolean, Long> collect1 = integers.stream().collect(Collectors.partitioningBy(x -> x % 2 == 0 , Collectors.counting())); System.out.println("能否被2整除,进行分组,并统计每组数量 -> " + collect1 + "" );
4.更多方法
查看文档,更多方法