Java SE 8 流库(四)

1.8. 收集数据

<R,A> R collect(Collector<? super T,A,R> collector)   使用给定的收集器来收集当前流中的元素

void forEach(Consumer<? super T> action)          对此流的每个元素执行操作

void forEachOrdered(Consumer<? super T> action)   为流的每个元素执行操作,如果流具有已定义的遇到顺序,则按流的遇到顺序执行操作

Object[] toArray()                              返回包含此流的元素的数组

Stream.toArray(),会返回一个Object[]数组,如果想要数组具有正确的类型,可以将其传递到数组构造器中;

static <T> Stream<T> iterate(T seed,UnaryOperator<T> f)   返回一个由函数f迭代应用到初始元素种子产生的无限顺序排序流,产生由种子,f(种子),f(f(种子))等组成的流。Stream中的第一个元素(位置0)将是提供的种子。 对于n> 0,位置n处的元素将是对位置n-1处的元素应用函数f的结果

Iterator<T> iterator()                     返回此流的元素的迭代器

public static <T> Collector<T,?,List<T>> toList()

public static <T> Collector<T,?,Set<T>> toSet()     将产生的元素收集到列表或集合中的收集器;

public static <T,C extends Collection<T>> Collector<T,?,C> toCollection(Supplier<C> collectionFactory)

产生一个将元素收集到集合中的收集器,可以传递一个诸如TreeSet :: new的构造器引用;

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)(前缀和后缀)

产生一个连接字符串的收集器,分隔符会置于字符串之间,而第一个字符串之前可以有前缀和最后一个字符串可以有后缀,如果没有指定,那么它们都为空;

public static <T> Collector<T,?,IntSummaryStatistics> summarizingInt(ToIntFunction<? super T> mapper)

public static <T> Collector<T,?,LongSummaryStatistics> summarizingLong(ToLongFunction<? super T> mapper)

public static <T> Collector<T,?,DoubleSummaryStatistics> summarizingDouble(ToDoubleFunction<? super T> mapper)

产生能够生成(int|long|double) SummaryStatistics对象收集器,通过它可以获得将Mapper应用于每个元素后产生的结果的个数,总和,平均值,最大值,和最小值

public class IntSummaryStatistics extends Object implements IntConsumer 对象中的方法:

public final int getMax()

public final double getAverage()

public final int getMax()

public final int getMin()

public final long getSum()

 1 package com.itheima05.Test_JavaSE.Test_20180101;
 2 
 3 import java.nio.charset.StandardCharsets;
 4 import java.nio.file.Files;
 5 import java.nio.file.Paths;
 6 import java.util.*;
 7 import java.util.stream.Collectors;
 8 import java.util.stream.Stream;
 9 
10 /**
11  * Created by Lenovo on 2018/1/1.
12  */
13 public class Demo01 {
14 
15     private static final String filePath = "G:\\Idea\\src\\com\\itheima05\\Test_JavaSE\\Test_20180101\\word.txt";
16 
17 
18     public static void main(String[] args) throws Exception{
19 
20         //实例1(iterate)
21         Iterator<Integer> it = Stream.iterate(0, n -> n + 1)
22                 .limit(10).iterator();
23         while (it.hasNext()){
24             System.out.println(it.next());
25         }
26 
27         Object[] numbers = Stream.iterate(0, n -> n + 1)
28                 .limit(10)
29                 .toArray();
30         //得到一个数组
31         System.out.println("numbers:"+numbers);
32 
33         //获取数组中的第一个元素
34         int number = (int)numbers[0];
35         System.out.println("number:"+ number);
36 
37         //强转为int数组(会有转化异常出现)
38         try {
39             Integer[] intNum = (Integer[]) numbers;
40             System.out.println("Integer[]:"+intNum);
41         } catch (Exception e) {
42             System.out.println(e);
43         }
44 
45         //将数组的正确类型传递到数组的构造器中
46         Integer[] arrayNums = Stream.iterate(0, n -> n + 1)
47                 .limit(10).toArray(Integer[]::new);
48         System.out.println("arrayNums:" + arrayNums);
49 
50         //转化为set集合
51         Set<String> noVowelsSet = noVowels().collect(Collectors.toSet());
52         show("noVowelsSet",noVowelsSet);
53 
54         //TreeSet
55         TreeSet<String> noVowelsTreeSet = noVowels().collect(Collectors.toCollection(TreeSet::new));
56         show("noVowelsTreeSet",noVowelsTreeSet);
57 
58         //joining
59         String noVowelsJoining = noVowels().limit(10).collect(Collectors.joining());
60         System.out.println("noVowelsJoining:"+noVowelsJoining);
61 
62         //joining(",")
63         String noVowelsJoining2 = noVowels().limit(10).collect(Collectors.joining(","));
64         System.out.println("noVowelsJoining2:"+noVowelsJoining2);
65 
66         //summarizingInt
67         IntSummaryStatistics summary = noVowels().collect(Collectors.summarizingInt(String::length));
68         double average = summary.getAverage();
69         int max = summary.getMax();
70         long count = summary.getCount();
71         System.out.println("average:"+average);
72         System.out.println("max:"+max);
73         System.out.println("count:"+count);
74 
75         //forEach
76         System.out.println("forEach:");
77         noVowels().limit(10).forEach(System.out::println);
78     }
79     public static Stream<String> noVowels() throws Exception{
80 
81         String contens = new String(Files.readAllBytes(Paths.get(filePath)), StandardCharsets.UTF_8);
82         List<String> wordList = Arrays.asList(contens.split("\\PL+"));
83         Stream<String> words = wordList.stream();
84         return words.map(s -> s.replaceAll("[aeiouAEIOU]",""));
85     }
86 
87     public static <T> void show(String label, Set<T> set) {
88 
89         System.out.println(label + ":" + set.getClass().getName());
90         System.out.println("{" + set.stream()
91                 .limit(10)
92                 .map(Object::toString)
93                 .collect(Collectors.joining(",")) + "}");
94     }
95 }

 1.9. 收集到映射表中

场景1:

假设我们有一个Stream<Person>,并且想要将其元素收集到一个映射表中,这样后续就可以通过他们的ID来查找人员了;

public static <T,K,U> Collector<T,?,Map<K,U>> toMap(Function<? super T,? extends K> keyMapper,

Function<? super T,? extends U> valueMapper)

该方法有两个函数引元,keyMapper和valueMapper

在通常情况下,值应该是实际元素,因此第二个函数可以使用Function.identity();

场景2:

如果有多个元素具有相同的键,那么就会存在冲突,收集器将会抛出一个IllegalStateException对象。可以通过提过3个函数引元来覆盖这种行为,该函数会针对给定的已有的值和新值来解决冲突并确定键对应的值。这个函数应该返回已有值,新值,或它们的组合;

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)

场景3:

假设我们想要了解给定国家的所有语言,这样我们就需要一个Map<String,Set<String>>;

例如:卢森堡=[德文, 法文]

首先我们为每一种语言都存储一个单例集,无论如何是,只要找到了给定的国家的新语言,我们都会将已有的集和新集做并操作;

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)

实例1:

Person类:

 1 public class Person {
 2 
 3     private int id;
 4     private String name;
 5 
 6     public Person(int id, String name) {
 7         this.id = id;
 8         this.name = name;
 9     }
10     public int getId() {
11         return id;
12     }
13     public void setId(int id) {
14         this.id = id;
15     }
16     public String getName() {
17         return name;
18     }
19     public void setName(String name) {
20         this.name = name;
21     }
22     @Override
23     public String toString() {
24         return "Person{" +
25                 "id=" + id +
26                 ", name='" + name + '\'' +
27                 '}';
28     }
29 }

CollectingIntoMaps类:

 1 public class CollectingIntoMaps {
 2 
 3 
 4     public static void main(String[] args) {
 5 
 6         //通过id查找Name
 7         Map<Integer, String> idToName = person().
 8                 collect(Collectors.toMap(Person::getId, Person::getName));
 9         System.out.println("idToName:"+idToName);
10         //输出
11         //idToName:{1001=xiaoming, 1002=xiaohei, 1003=xiaobao}
12 
13         //通过id查找Name(第二种方法)
14         Map<Integer, Person> idToName2 = person().
15                 collect(Collectors.toMap(Person::getId, Function.identity()));
16         System.out.println("idToName2:"+idToName2);
17         //输出2
18         //idToName2:{1001=Person{id=1001, name='xiaoming'},
19         //1002=Person{id=1002, name='xiaohei'},
20         //1003=Person{id=1003, name='xiaobao'}}
21         Map<Integer, Person> idToName3 = person().
22                 collect(Collectors.toMap(Person::getId, Function.identity(),
23                         (existingValue,newValue) ->
24                         {throw new IllegalStateException();},TreeMap::new));
25         //默认情况下,当两个元素产生相同的键时,会抛出IllegalStateException异常
26         System.out.println("idToName3:"+idToName3.getClass().getName()+idToName3);
27     }
28 
29     public static Stream<Person> person(){
30 
31         return Stream.of(new Person(1001,"xiaoming"),
32                 new Person(1002,"xiaohei"),new Person(1003,"xiaobao"));
33     }
34 
35 }

实例2:

 1 public class Demo02 {
 2 
 3     public static void main(String[] args) {
 4 
 5         Stream<Locale> locales = Stream.of(Locale.getAvailableLocales());
 6         Map<String, String> languageNames = locales.collect(Collectors.toMap(Locale::getDisplayLanguage,
 7                 l -> l.getDisplayLanguage(l),
 8                 (existingValue, newValue) -> existingValue));
 9         System.out.println("languageNames:"+languageNames);
10 
11         //
12         locales = Stream.of(Locale.getAvailableLocales());
13         Map<String, Set<String>> countryLanguageSets = locales.collect(Collectors.toMap(Locale::getDisplayCountry,
14                 l -> Collections.singleton(l.getDisplayLanguage()),
15                 (a, b) -> {
16                     Set<String> union = new HashSet<>(a);
17                     union.addAll(b);
18                     return union;
19                 }));
20         System.out.println("countryLanguageSets:"+countryLanguageSets);
21     }
22 }

1.10. 群组和分区

public static <T,K> Collector<T,?,Map<K,List<T>>> groupingBy(Function<? super T,? extends K> classifier)

public static <T,K> Collector<T,?,ConcurrentMap<K,List<T>>> groupingByConcurrent(Function<? super T,? extends K> classifier)

产生一个收集器,它会产生一个映射表或并发映射表,其键是将classifier应用于所有收集到的元素上所产生的的结果,而值是有具有相同键的元素构成的一个个列表;

public static <T> Collector<T,?,Map<Boolean,List<T>>> partitioningBy(Predicate<? super T> predicate)

产生一个收集器,它会产生一个映射表,其键是true/false,而值是有满足/不满足断言的元素构成的列表;

实例:

 1 **
 2  * Created by Lenovo on 2018/1/3.
 3  * public static Locale[] getAvailableLocales()
 4  * public String getCountry()
 5  */
 6 public class Demo03 {
 7 
 8     public static void main(String[] args) {
 9 
10         //集组
11         Stream<Locale> locales = Stream.of(Locale.getAvailableLocales());
12         Map<String, List<Locale>> countryToLocale = locales.
13                 collect(Collectors.groupingBy(Locale::getCountry));
14         List<Locale> localeList = countryToLocale.get("CH");
15         System.out.println(localeList);
16 
17         //分区
18         locales = Stream.of(Locale.getAvailableLocales());
19         Map<Boolean, List<Locale>> languageToLocale = locales.
20                 collect(Collectors.partitioningBy(l -> l.getLanguage().equals("en")));
21         System.out.println(languageToLocale.get(true));
22     }
23 }

当分类函数是断言函数(返回boolean值的函数)时,流的元素可以使用分区为两个列表:该函数返回true的元素和其他元素,这种情况下,使用partitioningBy比使用groupingBy更高效;

posted @ 2018-01-01 22:37  追逐新梦想  阅读(973)  评论(0编辑  收藏  举报