Java-8-Collectors类
final class Collectors
思维导图:
Stream 的核心在于Collectors,即对处理后的数据进行收集。Collectors 提供了非常多且强大的API,可以将最终的数据收集成List、Set、Map,甚至是更复杂的结构(这三者的嵌套组合)。
toList
源码:
public static <T>
Collector<T, ?, List<T>> toList() {
return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
(left, right) -> { left.addAll(right); return left; },
CH_ID);
}
将数据收集进一个列表(Stream 转换为 List,允许重复值,有顺序)
使用
public class M1 {
public static void main(String[] args) {
List<String> list = Stream.of("AA","BB","CC").collect(Collectors.toList());
list.forEach(s->System.out.println(s));
System.out.println("----------");
List<Integer> l1 = Create_Data.supply_Integers();
// 收集偶数到集合里面
List<Integer> even = l1.stream()
.filter(integer -> integer % 2 == 0)
.collect(Collectors.toList());
System.out.println(even);
}
}
toSet
源码:
public static <T>
Collector<T, ?, Set<T>> toSet() {
return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, Set::add,
(left, right) -> { left.addAll(right); return left; },
CH_UNORDERED_ID);
}
将数据收集进一个集合(Stream 转换为 Set,不允许重复值,没有顺序)
使用
public class M1 {
public static void main(String[] args) {
Set<String> set = Stream.of("AA","AA","BB").collect(Collectors.toSet());
set.forEach(s->System.out.println(s));
}
}
toCollection
源码:
public static <T, C extends Collection<T>>
Collector<T, ?, C> toCollection(Supplier<C> collectionFactory) {
return new CollectorImpl<>(collectionFactory, Collection<T>::add,
(r1, r2) -> { r1.addAll(r2); return r1; },
CH_ID);
}
Collectors.toCollection() 将数据转成Collection,只要是Collection 的实现都可以,例如ArrayList、HashSet ,该方法接受一个Collection 的实现对象或者说Collection 工厂的入参
使用
public class M1 {
public static void main(String[] args) {
List<String> l1 = Stream.of(
"kdkkd","kdkdkkd","lokfkf"
).collect(Collectors.toCollection(ArrayList::new));
System.out.println(l1);
System.out.println("-------------");
Set<String> set1 = Stream.of("a","a","bb")
.collect(Collectors.toCollection(HashSet::new));
System.out.println(set1);
}
}
toMap
源码:
// * <p>If the mapped keys contains duplicates (according to
// * {@link Object#equals(Object)}), an {@code IllegalStateException} is
// * thrown when the collection operation is performed. If the mapped keys
// * may have duplicates, use {@link #toMap(Function, Function, BinaryOperator)}
// * instead.
// * @param <T> the type of the input elements
// * @param <K> the output type of the key mapping function
// * @param <U> the output type of the value mapping function
// * @param keyMapper a mapping function to produce keys
// * @param valueMapper a mapping function to produce values
// * @return a {@code Collector} which collects elements into a {@code Map}
// * whose keys and values are the result of applying mapping functions to
// * the input elements
public static <T, K, U>
Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper) {
return toMap(keyMapper, valueMapper, throwingMerger(), HashMap::new);
}
// * <p>If the mapped
// * keys contains duplicates (according to {@link Object#equals(Object)}),
// * the value mapping function is applied to each equal element, and the
// * results are merged using the provided merging function.
// * @param <T> the type of the input elements
// * @param <K> the output type of the key mapping function
// * @param <U> the output type of the value mapping function
// * @param keyMapper a mapping function to produce keys
// * @param valueMapper a mapping function to produce values
// * @param mergeFunction a merge function, used to resolve collisions between
// * values associated with the same key, as supplied
// * to {@link Map#merge(Object, Object, BiFunction)}
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) {
return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);
}
// * @param <T> the type of the input elements
// * @param <K> the output type of the key mapping function
// * @param <U> the output type of the value mapping function
// * @param <M> the type of the resulting {@code Map}
// * @param keyMapper a mapping function to produce keys
// * @param valueMapper a mapping function to produce values
// * @param mergeFunction a merge function, used to resolve collisions between
// * values associated with the same key, as supplied
// * to {@link Map#merge(Object, Object, BiFunction)}
// * @param mapSupplier a function which returns a new, empty {@code Map} into
// * which the results will be inserted
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) {
BiConsumer<M, T> accumulator
= (map, element) -> map.merge(keyMapper.apply(element),
valueMapper.apply(element), mergeFunction);
return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID);
}
第一个
如果遇到键重复的情况会抛出IllegalStateException异常
使用
public class Student {
static private Random random = new Random();
static private DecimalFormat df = new DecimalFormat("0.00");
private int id;
private String name;
private int age;
private int G_math;
private int G_english;
private int G_chinese;
public Student(int id, String name, int age, int g_math, int g_english, int g_chinese) {
this.id = id;
this.name = name;
this.age = age;
G_math = g_math;
G_english = g_english;
G_chinese = g_chinese;
}
public Student(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", G_math=" + G_math +
", G_english=" + G_english +
", G_chinese=" + G_chinese +
'}';
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
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 int getG_math() {
return G_math;
}
public void setG_math(int g_math) {
G_math = g_math;
}
public int getG_english() {
return G_english;
}
public void setG_english(int g_english) {
G_english = g_english;
}
public int getG_chinese() {
return G_chinese;
}
public void setG_chinese(int g_chinese) {
G_chinese = g_chinese;
}
public static int computeGPA(Student student){
return (student.getG_chinese() + student.getG_english() + student.getG_math()) / 3;
}
public static List<Student> supple_S(){
List<Student> d = new ArrayList<>();
for (int i = 0; i < 20; i++) {
d.add(new Student(i,i+"号学生",random.nextInt(25),random.nextInt(100),random.nextInt(100),random.nextInt(100)));
}
return d;
}
public static void main(String[] args) {
supple_S().stream()
.forEach(System.out::println);
}
}
public class M1 {
// * <pre>{@code
// * Map<Student, Double> studentToGPA
// * students.stream().collect(toMap(Functions.identity(),
// * student -> computeGPA(student)));
// * }</pre>
// * And the following produces a {@code Map} mapping a unique identifier to
// * students:
// * <pre>{@code
// * Map<String, Student> studentIdToStudent
// * students.stream().collect(toMap(Student::getId,
// * Functions.identity());
// * }</pre>
public static void main(String[] args) {
List<Student> students = Student.supple_S();
Map<Student,Integer> studentToGPA = students.stream()
.collect(Collectors.toMap(Function.identity(),student -> Student.computeGPA(student)));
// System.out.println(studentToGPA);
studentToGPA.forEach(
(k,v) ->
System.out.println(k + "---" + v)
);
System.out.println("----------------");
Map<Integer, Student> studentIdToStudent = students.stream()
.collect(Collectors.toMap(Student::getId,Function.identity()));
studentIdToStudent.forEach(
(k,v) ->
System.out.println(k + "---" + v)
);
System.out.println("----------------");
Map<String,String> map = Stream.of("AA","BB","CC").collect(Collectors.toMap(k->k, v->v+v));
map.forEach((k,v)->System.out.println("key:"+k +" value:"+v));
}
}
第二个
mergeFunction是解决当key相同时,取哪个value的问题,由返回值指定,当返回null时,从map中移除当前entry
当遇到重复的键时,API文档给出的做法是相同key的情况下,把value变成list,形成Map(Object,List)的形式
// * <pre>{@code
// * Map<String, String> phoneBook
// * people.stream().collect(toMap(Person::getName,
// * Person::getAddress,
// * (s, a) -> s + ", " + a));
// * }</pre>
使用
public class Person {
private static String[]