StreamストリームとLambda式(3)静的ファクトリクラスCollectors


/**
 * @author   
 */

@SpringBootTest
@RunWith(SpringRunner.class)
public class CollectorsDetail {

    private List names;
    private List students;
    private List> snames;

    @Before
    public void init() {

        names = Arrays.asList("Kirito", "Asuna", "Sinon", "Yuuki", "Alice");
        snames = Arrays.asList(Collections.singletonList("Kirito"), Collections.singletonList("Asuna"),
                Collections.singletonList("Sinon"), Collections.singletonList("Yuuki"),
                Collections.singletonList("Alice"));

        students = new Students().init();
    }

    @Test
    public void testCollectorsDetail() {

一、静的工場類Collectors実現方式
//     、     Collectors     

//    Collectors            CollectorImpl  
//       1、   CollectorImpl  
//       2、   reducing()  ---> reducing()   CollectorImpl  


//    Collectors.toList()    Collectors.toCollection()         
//    Collectors.joining()   StringBuilder.append      

二、静的工場類Collectors常用コレクター
//     、     Collectors      

/*
          (    )unmodifiable List ArrayList         encounter order
@since 10
@SuppressWarnings("unchecked")
public static 
        Collector> toUnmodifiableList() {
    return new CollectorImpl<>((Supplier>) ArrayList::new, List::add,
            (left, right) -> { left.addAll(right); return left; },
            list -> (List)List.of(list.toArray()),
            CH_NOID);
}*/


/*
          (    )unmodifiable Set HashSet   
@since 10
@SuppressWarnings("unchecked")
public static 
        Collector> toUnmodifiableSet() {
    return new CollectorImpl<>((Supplier>) HashSet::new, Set::add,
            (left, right) -> {
                if (left.size() < right.size()) {
                    right.addAll(left); return right;
                } else {
                    left.addAll(right); return left;
                }
            },
            set -> (Set)Set.of(set.toArray()),
            CH_UNORDERED_NOID);
}
*/


/*
          flatMapping   mapper     downstream                   
@since 9
public static 
        Collector flatMapping(Function super T, ? extends Stream extends U>> mapper,
        Collector super U, A, R> downstream) {
    BiConsumerdownstreamAccumulator = downstream.accumulator();
return new CollectorImpl<>(downstream.supplier(),
(r, t) -> {
try (Stream extends U> result = mapper.apply(t)) {
if (result != null)
result.sequential().forEach(u -> downstreamAccumulator.accept(r, u));
}
},
downstream.combiner(), downstream.finisher(),
downstream.characteristics());
}*/
/*
Predicateの    に  するフィルタリングfiltering downstreamを  して  を  
@since 9
public static 
Collector filtering(Predicate super T> predicate,
Collector super T, A, R> downstream) {
BiConsumerdownstreamAccumulator = downstream.accumulator();
return new CollectorImpl<>(downstream.supplier(),
(r, t) -> {
if (predicate.test(t)) {
downstreamAccumulator.accept(r, t);
}
},
downstream.combiner(), downstream.finisher(),
downstream.characteristics());
}*/
/*
Mapを  してkey-->keyMapper-->Key value-->valueMapper-->Value
マッピングした  をアセンブリするentrySet->Map(unmodifiable Map)
@since 10
@SuppressWarnings({"rawtypes", "unchecked"})
public static 
Collector> toUnmodifiableMap(Function super T, ? extends K> keyMapper,
Function super T, ? extends U> valueMapper) {
Objects.requireNonNull(keyMapper, "keyMapper");
Objects.requireNonNull(valueMapper, "valueMapper");
return collectingAndThen(
toMap(keyMapper, valueMapper),
map -> (Map)Map.ofEntries(map.entrySet().toArray(new Map.Entry[0])));
}*/
/*
Mapを  してkey-->keyMapper-->Key value-->valueMapper-->Value
mergeFunction じkeyマッピング のValueマージ  
マッピングした  をアセンブリするentrySet->Map(unmodifiable Map)
@since 10
@SuppressWarnings({"rawtypes", "unchecked"})
public static 
Collector> toUnmodifiableMap(Function super T, ? extends K> keyMapper,
Function super T, ? extends U> valueMapper,
BinaryOperator mergeFunction) {
Objects.requireNonNull(keyMapper, "keyMapper");
Objects.requireNonNull(valueMapper, "valueMapper");
Objects.requireNonNull(mergeFunction, "mergeFunction");
return collectingAndThen(
toMap(keyMapper, valueMapper, mergeFunction, HashMap::new),
map -> (Map)Map.ofEntries(map.entrySet().toArray(new Map.Entry[0])));
}*/
//    Collectors    
System.out.println("-----------------------------------------
"); // ArrayList List unmodifiableList = names.stream().collect(Collectors.toUnmodifiableList()); System.out.println(unmodifiableList); System.out.println("---------------------------------------
"); // HashSet Set unmodifiableSet = names.stream().collect(Collectors.toUnmodifiableSet()); System.out.println(unmodifiableSet); System.out.println("---------------------------------------
"); // ArrayList List strings = snames.stream() .collect(Collectors.flatMapping(list -> list.stream().map(String::toUpperCase), Collectors.toList())); System.out.println(strings); System.out.println("---------------------------------------
"); // ArrayList List filteringPredicate = names.stream().collect(Collectors.filtering("Kirito"::equals, Collectors.toList())); System.out.println(filteringPredicate); System.out.println("---------------------------------------
"); // key-->keyMapper value-->valueMapper Map Map> listMap = students.stream() .collect(Collectors.toUnmodifiableMap(Student::getId, student -> { List stus = new ArrayList<>(); stus.add(student); return stus; })); System.out.println(listMap); System.out.println("---------------------------------------
"); // key-->keyMapper-->Key value-->valueMapper-->Value // Key Value Map lengthName = names.stream() .collect(Collectors.toUnmodifiableMap(String::length, String::toString, (str1, str2) -> str1 + "\t" + str2)); System.out.println(lengthName); System.out.println("---------------------------------------
");

三、groupingByグループ
//     、groupingBy  

//       groupingBy

//     T    key     -->       classifier-->        value-->    Map
/*
Returns a {@code Collector} implementing a "group by" operation on
input elements of type {@code T}, grouping elements according to a
         classification function, and returning the results in a {@code Map}.

The classification function maps elements to some key type {@code K}. The collector produces a {@code Map>} whose keys are the values resulting from applying the classification function to the input elements, and whose corresponding values are {@code List}s containing the input elements which map to the associated key under the classification function.

There are no guarantees on the type, mutability, serializability, or thread-safety of the {@code Map} or {@code List} objects returned.*/ /* key T classifier List public static Collector>> groupingBy(Function super T, ? extends K> classifier) { return groupingBy(classifier, toList()); }*/ /* key T classifier downstream public static Collector> groupingBy(Function super T, ? extends K> classifier, Collector super T, A, D> downstream) { return groupingBy(classifier, HashMap::new, downstream); }*/ /* key T classifier mapFactory downstream CollectorImpl downstream public static > Collector groupingBy(Function super T, ? extends K> classifier, Supplier mapFactory, Collector super T, A, D> downstream) { SupplierdownstreamSupplier = downstream.supplier(); BiConsumerdownstreamAccumulator = downstream.accumulator(); BiConsumer, T> accumulator = (m, t) -> { K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key"); A container = m.computeIfAbsent(key, k -> downstreamSupplier.get()); downstreamAccumulator.accept(container, t); }; BinaryOperator> merger = Collectors.>mapMerger(downstream.combiner()); @SuppressWarnings("unchecked") Supplier> mangledFactory = (Supplier>) mapFactory; // なしでCollectorImplを if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) { return new CollectorImpl<>(mangledFactory, accumulator, merger, CH_ID); } else { // によるCollectorImplの @SuppressWarnings("unchecked") FunctiondownstreamFinisher = (Function) downstream.finisher(); Function, M> finisher = intermediate -> { intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v)); @SuppressWarnings("unchecked") M castResult = (M) intermediate; return castResult; }; return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_NOID); } }*/

//      
System.out.println("-----------------------------------------
"); // select * from students group by sex ; Map> sexStudent = students.stream().collect(Collectors.groupingBy(Student::getSex)); System.out.println(sexStudent); System.out.println("-----------------------------------------
"); // select sex, count(*) from students group by sex ; Map sexCount = students.stream().collect(Collectors.groupingBy(Student::getSex, Collectors.counting())); System.out.println(sexCount); System.out.println("-----------------------------------------
"); // select sex,avg(salary) from students group by sex ; Map avgSexSalary = students.stream().collect (Collectors.groupingBy(Student::getSex, Collectors.averagingDouble(Student::getSalary))); System.out.println(avgSexSalary); System.out.println("-----------------------------------------
"); // sex addr Map>> NestedGroupBy = students.stream() .collect(Collectors.groupingBy(Student::getSex, Collectors.groupingBy(Student::getAddr))); System.out.println(NestedGroupBy); System.out.println("-----------------------------------------
"); // downstream HashSet Map> sexHashSet = students.stream() .collect(Collectors.groupingBy(Student::getSex, Collectors.toCollection(HashSet::new))); System.out.println(sexHashSet); System.out.println("-----------------------------------------
"); // downstream HashSet CollectorImpl Map> sexCustomCollectorImpl = students.stream() .collect(Collectors.groupingBy(Student::getSex, Hashtable::new, Collectors.toCollection(HashSet::new))); System.out.println(sexCustomCollectorImpl); System.out.println("-----------------------------------------
");

四、groupingByConcurrentグループ
 //     、groupingByConcurrent  

 //       groupingByConcurrent

 //          :
 //             Collector.Characteristics.UNORDERED
 //             Collector.Characteristics.CONCURRENT
 //    This is a {@link Collector.Characteristics#CONCURRENT concurrent} and
 //    {@link Collector.Characteristics#UNORDERED unordered} Collector.


 /*
         key T  classifier  
         List        
 public static 
         Collector>>
 groupingByConcurrent(Function super T, ? extends K> classifier) {
     return groupingByConcurrent(classifier,  ::new, toList());
 }*/


/*
         key T  classifier  
               downstream       
public static 
         Collector> groupingByConcurrent(Function super T, ? extends K> classifier,
         Collector super T, A, D> downstream) {
     return groupingByConcurrent(classifier, ConcurrentHashMap::new, downstream);
 }*/


 /*
         key T  classifier  
               mapFactory    downstream CollectorImpl  
               downstream       
 public static >
 Collector groupingByConcurrent(Function super T, ? extends K> classifier,
         Supplier mapFactory,
         Collector super T, A, D> downstream) {
     SupplierdownstreamSupplier = downstream.supplier();
BiConsumerdownstreamAccumulator = downstream.accumulator();
BinaryOperator> merger = Collectors.>mapMerger(downstream.combiner());
@SuppressWarnings("unchecked")
Supplier> mangledFactory = (Supplier>) mapFactory;
BiConsumer, T> accumulator;
if (downstream.characteristics().contains(Collector.Characteristics.CONCURRENT)) {
accumulator = (m, t) -> {
K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key");
A resultContainer = m.computeIfAbsent(key, k -> downstreamSupplier.get());
downstreamAccumulator.accept(resultContainer, t);
};
}
else {
accumulator = (m, t) -> {
K key = Objects.requireNonNull(classifier.apply(t), "element cannot be mapped to a null key");
A resultContainer = m.computeIfAbsent(key, k -> downstreamSupplier.get());
//  のアクション--> じ  コンテナを  に  --> じ  、  のアクションは1つのみ-->スレッド  
synchronized (resultContainer) {
downstreamAccumulator.accept(resultContainer, t);
}
};
}
if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
return new CollectorImpl<>(mangledFactory, accumulator, merger, CH_CONCURRENT_ID);
}
else {
@SuppressWarnings("unchecked")
FunctiondownstreamFinisher = (Function) downstream.finisher();
Function, M> finisher = intermediate -> {
intermediate.replaceAll((k, v) -> downstreamFinisher.apply(v));
@SuppressWarnings("unchecked")
M castResult = (M) intermediate;
return castResult;
};
return new CollectorImpl<>(mangledFactory, accumulator, merger, finisher, CH_CONCURRENT_NOID);
}
}*/
//            
System.out.println("-----------------------------------------
"); // ArrayList ConcurrentMap> sexStudentConcurrent = students.stream() .collect(Collectors.groupingByConcurrent(Student::getSex)); System.out.println(sexStudentConcurrent); System.out.println("-----------------------------------------
"); // downstream HashSet ConcurrentMap> sexHashSetConcurrent = students.stream() .collect(Collectors.groupingByConcurrent(Student::getSex, Collectors.toCollection(HashSet::new))); System.out.println(sexHashSetConcurrent); System.out.println("-----------------------------------------
"); // downstream HashSet CollectorImpl ConcurrentReferenceHashMap> sexCustomCollectorImplConcurrent = students.stream().collect(Collectors.groupingByConcurrent(Student::getSex, ConcurrentReferenceHashMap::new, Collectors.toCollection(HashSet::new))); System.out.println(sexCustomCollectorImplConcurrent); System.out.println("-----------------------------------------
");

五、partitioningByパーティション
//     、partitioningBy  

//      partitioningBy

/*
                      ArrayList        
public static 
        Collector>> partitioningBy(Predicate super T> predicate) {
    return partitioningBy(predicate, toList());
}*/


/*
                            downstream        
public static 
        Collector> partitioningBy(Predicate super T> predicate,
        Collector super T, A, D> downstream) {
    BiConsumerdownstreamAccumulator = downstream.accumulator();
BiConsumer, T> accumulator = (result, t) ->
downstreamAccumulator.accept(predicate.test(t) ? result.forTrue : result.forFalse, t);
BinaryOperatorop = downstream.combiner();
BinaryOperator> merger = (left, right) ->
new Partition<>(op.apply(left.forTrue, right.forTrue),
op.apply(left.forFalse, right.forFalse));
Supplier> supplier = () ->
new Partition<>(downstream.supplier().get(),
downstream.supplier().get());
if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
return new CollectorImpl<>(supplier, accumulator, merger, CH_ID);
}
else {
Function, Map> finisher = par ->
new Partition<>(downstream.finisher().apply(par.forTrue),
downstream.finisher().apply(par.forFalse));
return new CollectorImpl<>(supplier, accumulator, merger, finisher, CH_NOID);
}
}*/
        //      
        System.out.println("-----------------------------------------
"); // select * from students partition by (addr == Sword Art Online) ; Map> addrPartition = students.stream().collect (Collectors.partitioningBy(student -> student.getAddr().equals("Sword Art Online"))); System.out.println(addrPartition); System.out.println("-----------------------------------------
"); // sex addr Map>> NestedPartiton = students.stream() .collect(Collectors.partitioningBy(student -> student.getSex().equals("Male"), Collectors.partitioningBy(student -> student.getAddr().equals("Sword Art Online")))); System.out.println(NestedPartiton); System.out.println("-----------------------------------------
"); // downstream Map> addrCustomPartition = students.stream().collect(Collectors.partitioningBy (student -> student.getAddr().equals("Sword Art Online"), Collectors.toCollection(HashSet::new))); System.out.println(addrCustomPartition); System.out.println("-----------------------------------------
"); } }

六、テスト結果
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.2.RELEASE)

2019-02-20 16:58:15.870  INFO 13392 --- [           main] c.j.d.java8.Stream.CollectorsDetail      : Starting CollectorsDetail on DESKTOP-87RMBG4 with PID 13392 (started by 46250 in E:\IdeaProjects\design)
2019-02-20 16:58:15.871  INFO 13392 --- [           main] c.j.d.java8.Stream.CollectorsDetail      : No active profile set, falling back to default profiles: default
2019-02-20 16:58:16.383  INFO 13392 --- [           main] c.j.d.java8.Stream.CollectorsDetail      : Started CollectorsDetail in 0.708 seconds (JVM running for 1.421)
-----------------------------------------

[Kirito, Asuna, Sinon, Yuuki, Alice]
---------------------------------------

[Yuuki, Asuna, Kirito, Sinon, Alice]
---------------------------------------

[KIRITO, ASUNA, SINON, YUUKI, ALICE]
---------------------------------------

[Kirito]
---------------------------------------

{5=[Student(id=5, name=Alice, sex=Female, age=14, addr=Alicization, salary=9.99999999E8)], 4=[Student(id=4, name=Yuuki, sex=Female, age=15, addr=Alfheim Online, salary=9.99999999E8)], 3=[Student(id=3, name=Sinon, sex=Female, age=16, addr=Gun Gale Online, salary=9.99999999E8)], 2=[Student(id=2, name=Asuna, sex=Female, age=17, addr=Sword Art Online, salary=9.99999999E8)], 1=[Student(id=1, name=Kirito, sex=Male, age=18, addr=Sword Art Online, salary=9.99999999E8)]}
---------------------------------------

{6=Kirito, 5=Asuna    Sinon    Yuuki    Alice}
---------------------------------------

-----------------------------------------

{Female=[Student(id=2, name=Asuna, sex=Female, age=17, addr=Sword Art Online, salary=9.99999999E8), Student(id=3, name=Sinon, sex=Female, age=16, addr=Gun Gale Online, salary=9.99999999E8), Student(id=4, name=Yuuki, sex=Female, age=15, addr=Alfheim Online, salary=9.99999999E8), Student(id=5, name=Alice, sex=Female, age=14, addr=Alicization, salary=9.99999999E8)], Male=[Student(id=1, name=Kirito, sex=Male, age=18, addr=Sword Art Online, salary=9.99999999E8)]}
-----------------------------------------

{Female=4, Male=1}
-----------------------------------------

{Female=9.99999999E8, Male=9.99999999E8}
-----------------------------------------

{Female={Alicization=[Student(id=5, name=Alice, sex=Female, age=14, addr=Alicization, salary=9.99999999E8)], Sword Art Online=[Student(id=2, name=Asuna, sex=Female, age=17, addr=Sword Art Online, salary=9.99999999E8)], Gun Gale Online=[Student(id=3, name=Sinon, sex=Female, age=16, addr=Gun Gale Online, salary=9.99999999E8)], Alfheim Online=[Student(id=4, name=Yuuki, sex=Female, age=15, addr=Alfheim Online, salary=9.99999999E8)]}, Male={Sword Art Online=[Student(id=1, name=Kirito, sex=Male, age=18, addr=Sword Art Online, salary=9.99999999E8)]}}
-----------------------------------------

{Female=[Student(id=4, name=Yuuki, sex=Female, age=15, addr=Alfheim Online, salary=9.99999999E8), Student(id=3, name=Sinon, sex=Female, age=16, addr=Gun Gale Online, salary=9.99999999E8), Student(id=5, name=Alice, sex=Female, age=14, addr=Alicization, salary=9.99999999E8), Student(id=2, name=Asuna, sex=Female, age=17, addr=Sword Art Online, salary=9.99999999E8)], Male=[Student(id=1, name=Kirito, sex=Male, age=18, addr=Sword Art Online, salary=9.99999999E8)]}
-----------------------------------------

{Female=[Student(id=4, name=Yuuki, sex=Female, age=15, addr=Alfheim Online, salary=9.99999999E8), Student(id=3, name=Sinon, sex=Female, age=16, addr=Gun Gale Online, salary=9.99999999E8), Student(id=5, name=Alice, sex=Female, age=14, addr=Alicization, salary=9.99999999E8), Student(id=2, name=Asuna, sex=Female, age=17, addr=Sword Art Online, salary=9.99999999E8)], Male=[Student(id=1, name=Kirito, sex=Male, age=18, addr=Sword Art Online, salary=9.99999999E8)]}
-----------------------------------------

-----------------------------------------

{Male=[Student(id=1, name=Kirito, sex=Male, age=18, addr=Sword Art Online, salary=9.99999999E8)], Female=[Student(id=2, name=Asuna, sex=Female, age=17, addr=Sword Art Online, salary=9.99999999E8), Student(id=3, name=Sinon, sex=Female, age=16, addr=Gun Gale Online, salary=9.99999999E8), Student(id=4, name=Yuuki, sex=Female, age=15, addr=Alfheim Online, salary=9.99999999E8), Student(id=5, name=Alice, sex=Female, age=14, addr=Alicization, salary=9.99999999E8)]}
-----------------------------------------

{Male=[Student(id=1, name=Kirito, sex=Male, age=18, addr=Sword Art Online, salary=9.99999999E8)], Female=[Student(id=4, name=Yuuki, sex=Female, age=15, addr=Alfheim Online, salary=9.99999999E8), Student(id=3, name=Sinon, sex=Female, age=16, addr=Gun Gale Online, salary=9.99999999E8), Student(id=5, name=Alice, sex=Female, age=14, addr=Alicization, salary=9.99999999E8), Student(id=2, name=Asuna, sex=Female, age=17, addr=Sword Art Online, salary=9.99999999E8)]}
-----------------------------------------

{Female=[Student(id=4, name=Yuuki, sex=Female, age=15, addr=Alfheim Online, salary=9.99999999E8), Student(id=3, name=Sinon, sex=Female, age=16, addr=Gun Gale Online, salary=9.99999999E8), Student(id=5, name=Alice, sex=Female, age=14, addr=Alicization, salary=9.99999999E8), Student(id=2, name=Asuna, sex=Female, age=17, addr=Sword Art Online, salary=9.99999999E8)], Male=[Student(id=1, name=Kirito, sex=Male, age=18, addr=Sword Art Online, salary=9.99999999E8)]}
-----------------------------------------

-----------------------------------------

{false=[Student(id=3, name=Sinon, sex=Female, age=16, addr=Gun Gale Online, salary=9.99999999E8), Student(id=4, name=Yuuki, sex=Female, age=15, addr=Alfheim Online, salary=9.99999999E8), Student(id=5, name=Alice, sex=Female, age=14, addr=Alicization, salary=9.99999999E8)], true=[Student(id=1, name=Kirito, sex=Male, age=18, addr=Sword Art Online, salary=9.99999999E8), Student(id=2, name=Asuna, sex=Female, age=17, addr=Sword Art Online, salary=9.99999999E8)]}
-----------------------------------------

{false={false=[Student(id=3, name=Sinon, sex=Female, age=16, addr=Gun Gale Online, salary=9.99999999E8), Student(id=4, name=Yuuki, sex=Female, age=15, addr=Alfheim Online, salary=9.99999999E8), Student(id=5, name=Alice, sex=Female, age=14, addr=Alicization, salary=9.99999999E8)], true=[Student(id=2, name=Asuna, sex=Female, age=17, addr=Sword Art Online, salary=9.99999999E8)]}, true={false=[], true=[Student(id=1, name=Kirito, sex=Male, age=18, addr=Sword Art Online, salary=9.99999999E8)]}}
-----------------------------------------

{false=[Student(id=4, name=Yuuki, sex=Female, age=15, addr=Alfheim Online, salary=9.99999999E8), Student(id=3, name=Sinon, sex=Female, age=16, addr=Gun Gale Online, salary=9.99999999E8), Student(id=5, name=Alice, sex=Female, age=14, addr=Alicization, salary=9.99999999E8)], true=[Student(id=2, name=Asuna, sex=Female, age=17, addr=Sword Art Online, salary=9.99999999E8), Student(id=1, name=Kirito, sex=Male, age=18, addr=Sword Art Online, salary=9.99999999E8)]}
-----------------------------------------