import com.sun.javafx.collections.UnmodifiableObservableMap;
import javax.print.attribute.UnmodifiableSetException;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
import static java.util.stream.Collector.Characteristics.CONCURRENT;
import static java.util.stream.Collector.Characteristics.IDENTITY_FINISH;
import static java.util.stream.Collector.Characteristics.UNORDERED;
/**
* 收集器:可变容器,对于目标流的动作
* 1.输入 Set<String>
* 2.输出 Map<String,String>
* 3.示例输入:["hello","world","hello world"]
* 4.示例输出:[{hello,hello},{world,world},{hello world,hello world}]
* 5.T,Set<T>,Map<T,T> ---- T(流中元素类型), A(中间结果容器类型), R(返回结果类型)
* 6.枚举特性IDENTITY_FINISH , UNORDERED ,CONCURRENT
* @ClassName MySetCollector
* @Author kate
*/
public class MySetCollector<T> implements Collector<T,Set<T>,Map<T,T>> {
/**
* A a1 = supplier.get();
* * accumulator.accept(a1, t1);
* * accumulator.accept(a1, t2);
* * R r1 = finisher.apply(a1); // result without splitting
* *
* * A a2 = supplier.get();
* * accumulator.accept(a2, t1);
* * A a3 = supplier.get();
* * accumulator.accept(a3, t2);
* * R r2 = finisher.apply(combiner.apply(a2, a3)); // result with splitting
* @return
*/
@Override
public Supplier<Set<T>> supplier() {
System.out.println("supplier ---->");
// return HashSet<T>::new;
return () -> {
System.out.println(" ---- ---- ");
// System.out.println("串行流 supplier调用1次 ---->");
// System.out.println("并行流 supplier调用线程次数个 生成CPU核心数的线程,itel超线程1变2核,4变8核 ---->");
return new HashSet<T>();
};
}
@Override
public BiConsumer<Set<T>, T> accumulator() {
System.out.println("accumulator ---->");
return (set,item) -> {
System.out.println("accumulator ---->" +set+" --->" + Thread.currentThread().getName()); //线程名
set.add(item);
};
}
/**
* 在并行情况下,且收集器本身没有CONCURRENT特性时会被调用,有不被调用
* @return
*/
@Override
public BinaryOperator<Set<T>> combiner() {
System.out.println("combiner ---->");
return (set1,set2) -> {
// System.out.println("set1 ---->" + set1); 证明是否被调用
// System.out.println("set2 ---->" + set2);
set1.addAll(set2);
return set1;
};
}
@Override
public Function<Set<T>, Map<T, T>> finisher() {
System.out.println("finisher ---->");
//Set<T> 转换成: Map<T, T>
return set -> {
Map<T, T> map = new HashMap<>();
set.stream().forEach(item -> map.put(item,item));
return map;
};
}
@Override
public Set<Characteristics> characteristics() {
System.out.println("characteristics ---->");
//IDENTITY_FINISH 完成器函数就是IDENTITY函数,A到R的类型转换是成功的,finisher()不执行,对于此例T,R类型不同,故会报错
//UNORDERED 无序的
//** CONCURRENT 并行的,多个线程会同时操作同一个结果容器 Collections.unmodifiableSet(EnumSet.of(UNORDERED,CONCURRENT));
//** 加CONCURRENT特性会不定频率的抛异常,主要是加 System.out.println("accumulator ---->" +set+" --->" + Thread.currentThread().getName());
//异常原因:多个线程操作一个结果容器,并发修改,一个线程去修改一个集合,另一个线程正在遍历迭代这个集合时,没有并发时则没有异常
//解决:并行情况下不要修改一个结果容器时同时遍历它
return Collections.unmodifiableSet(EnumSet.of(UNORDERED));
}
public static void main(String[] args){
List<String> list = Arrays.asList("hello","world","hello world","hello");
//串行流1.stream() ; 2.stream().sequential() ;
// Map<String,String> map = list.stream().collect(new MySetCollector2<>());
//parallelStream 多个线程操作多个结果容器(不加CONCURRENT)
//加CONCURRENT多个线程操作一个结果容器,则不需要再合并,合并会报错
//并行流1.parallelStream() ; 2.stream().parallel()
Map<String,String> map = list.parallelStream().collect(new MySetCollector2<>());
//parallel().sequential().parallel().sequential() 串联,看最后一个,其他无效
System.out.println("map --> " + map);
//finisher没调用,中间结果个返回一样时可不实现finisher(),不用编写抛异常就可以
}
}