Stream流与Lambda表达式(三) 静态工厂类Collectors

7次阅读

共计 22041 个字符,预计需要花费 56 分钟才能阅读完成。

/**
* @author 陈杨
*/

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

private List<String> names;
private List<Student> students;
private List<List<String>> 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 <T>
Collector<T, ?, List<T>> toUnmodifiableList() {
return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
(left, right) -> {left.addAll(right); return left; },
list -> (List<T>)List.of(list.toArray()),
CH_NOID);
}*/

/*
返回一个(不可修改)unmodifiable Set 的 HashSet 无序
@since 10
@SuppressWarnings(“unchecked”)
public static <T>
Collector<T, ?, Set<T>> toUnmodifiableSet() {
return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, Set::add,
(left, right) -> {
if (left.size() < right.size()) {
right.addAll(left); return right;
} else {
left.addAll(right); return left;
}
},
set -> (Set<T>)Set.of(set.toArray()),
CH_UNORDERED_NOID);
}
*/

/*
返回一个 flatMapping 扁平化 mapper 处理后 由 downstream 收集的 累加器处理的结果合并 单线程
@since 9
public static <T, U, A, R>
Collector<T, ?, R> flatMapping(Function<? super T, ? extends Stream<? extends U>> mapper,
Collector<? super U, A, R> downstream) {
BiConsumer<A, ? super U> downstreamAccumulator = 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 <T, A, R>
Collector<T, ?, R> filtering(Predicate<? super T> predicate,
Collector<? super T, A, R> downstream) {
BiConsumer<A, ? super T> downstreamAccumulator = 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<Key,Value> (unmodifiable Map)
@since 10
@SuppressWarnings({“rawtypes”, “unchecked”})
public static <T, K, U>
Collector<T, ?, Map<K,U>> 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<K,U>)Map.ofEntries(map.entrySet().toArray(new Map.Entry[0])));
}*/

/*
使用 Map 映射 key–>keyMapper–>Key value–>valueMapper–>Value
mergeFunction 对相同 key 映射后的进行 Value 合并操作
对映射后的结果进行组装 entrySet–>Map<Key,Value> (unmodifiable Map)

@since 10
@SuppressWarnings({“rawtypes”, “unchecked”})
public static <T, K, U>
Collector<T, ?, Map<K,U>> toUnmodifiableMap(Function<? super T, ? extends K> keyMapper,
Function<? super T, ? extends U> valueMapper,
BinaryOperator<U> mergeFunction) {
Objects.requireNonNull(keyMapper, “keyMapper”);
Objects.requireNonNull(valueMapper, “valueMapper”);
Objects.requireNonNull(mergeFunction, “mergeFunction”);
return collectingAndThen(
toMap(keyMapper, valueMapper, mergeFunction, HashMap::new),
map -> (Map<K,U>)Map.ofEntries(map.entrySet().toArray(new Map.Entry[0])));
}*/
// Collectors 收集器
System.out.println(“—————————————–\n”);

// 使用 ArrayList 集合 按照流中元素排列先后顺序 进行添加操作
List<String> unmodifiableList = names.stream().collect(Collectors.toUnmodifiableList());
System.out.println(unmodifiableList);
System.out.println(“—————————————\n”);

// 使用 HashSet 集合 对流中元素顺序 进行添加操作
Set<String> unmodifiableSet = names.stream().collect(Collectors.toUnmodifiableSet());
System.out.println(unmodifiableSet);
System.out.println(“—————————————\n”);

// 将集合扁平化展开 对其中的字符串的每个字母 进行大写转换 使用 ArrayList 对转换后的结果进行收集
List<String> strings = snames.stream()
.collect(Collectors.flatMapping(list -> list.stream().map(String::toUpperCase), Collectors.toList()));
System.out.println(strings);
System.out.println(“—————————————\n”);

// 对流中元素进行遍历 对符合预期要求的元素 使用 ArrayList 集合存放
List<String> filteringPredicate = names.stream().collect(Collectors.filtering(“Kirito”::equals,
Collectors.toList()));
System.out.println(filteringPredicate);
System.out.println(“—————————————\n”);

// 对流中元素进行遍历 对 key–>keyMapper value–>valueMapper 映射 得到 Map 集合
Map<Integer, List<Student>> listMap = students.stream()
.collect(Collectors.toUnmodifiableMap(Student::getId, student -> {
List<Student> stus = new ArrayList<>();
stus.add(student);
return stus;
}));

System.out.println(listMap);
System.out.println(“—————————————\n”);

// 对流中元素进行遍历 对 key–>keyMapper–>Key value–>valueMapper–>Value 映射
// 对满足相同 Key 的元素 Value 进行合并
Map<Integer, String> lengthName = names.stream()
.collect(Collectors.toUnmodifiableMap(String::length,
String::toString, (str1, str2) -> str1 + “\t” + str2));
System.out.println(lengthName);
System.out.println(“—————————————\n”);
三、groupingBy 分组
// 三、groupingBy 分组

// 分组 groupingBy

// 对 T 元素按 key 进行分组 –> 分组的依据 classifier–> 分组后的集合 value–> 得到 Map<key,value>
/*
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}.

<p>The classification function maps elements to some key type {@code K}.
The collector produces a {@code Map<K, List<T>>} 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.

<p>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 <T, K> Collector<T, ?, Map<K, List<T>>>
groupingBy(Function<? super T, ? extends K> classifier) {
return groupingBy(classifier, toList());
}*/

/*
按照 key 对 T 进行 classifier 分组
使用自定义收集器 downstream 收集分组结果 单线程 线程安全
public static <T, K, A, D>
Collector<T, ?, Map<K, D>> 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 <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) {
Supplier<A> downstreamSupplier = downstream.supplier();
BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
BiConsumer<Map<K, A>, 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<Map<K, A>> merger = Collectors.<K, A, Map<K, A>>mapMerger(downstream.combiner());
@SuppressWarnings(“unchecked”)
Supplier<Map<K, A>> mangledFactory = (Supplier<Map<K, A>>) mapFactory;
// 不进行强制类型转换 重构 CollectorImpl 实现
if (downstream.characteristics().contains(Collector.Characteristics.IDENTITY_FINISH)) {
return new CollectorImpl<>(mangledFactory, accumulator, merger, CH_ID);
}
else {
// 进行强制类型转换 重构 CollectorImpl 实现
@SuppressWarnings(“unchecked”)
Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher();
Function<Map<K, A>, 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(“—————————————–\n”);

// select * from students group by sex ;
Map<String, List<Student>> sexStudent =
students.stream().collect(Collectors.groupingBy(Student::getSex));
System.out.println(sexStudent);
System.out.println(“—————————————–\n”);

// select sex, count(*) from students group by sex ;
Map<String, Long> sexCount =
students.stream().collect(Collectors.groupingBy(Student::getSex, Collectors.counting()));
System.out.println(sexCount);
System.out.println(“—————————————–\n”);

// select sex,avg(salary) from students group by sex ;
Map<String, Double> avgSexSalary = students.stream().collect
(Collectors.groupingBy(Student::getSex, Collectors.averagingDouble(Student::getSalary)));
System.out.println(avgSexSalary);
System.out.println(“—————————————–\n”);

// 嵌套分组 先根据 sex 分组 再对结果按照 addr 进行分组
Map<String, Map<String, List<Student>>> NestedGroupBy = students.stream()
.collect(Collectors.groupingBy(Student::getSex, Collectors.groupingBy(Student::getAddr)));
System.out.println(NestedGroupBy);
System.out.println(“—————————————–\n”);

// 使用自定义收集器 downstream 按性别分组 使用 HashSet 进行 结果收集
Map<String, HashSet<Student>> sexHashSet = students.stream()
.collect(Collectors.groupingBy(Student::getSex, Collectors.toCollection(HashSet::new)));
System.out.println(sexHashSet);
System.out.println(“—————————————–\n”);

// 使用自定义收集器 downstream 按性别分组 使用 HashSet 进行 结果收集 重置 CollectorImpl 实现
Map<String, HashSet<Student>> sexCustomCollectorImpl = students.stream()
.collect(Collectors.groupingBy(Student::getSex, Hashtable::new, Collectors.toCollection(HashSet::new)));
System.out.println(sexCustomCollectorImpl);
System.out.println(“—————————————–\n”);
四、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 <T, K>
Collector<T, ?, ConcurrentMap<K, List<T>>>
groupingByConcurrent(Function<? super T, ? extends K> classifier) {
return groupingByConcurrent(classifier, ::new, toList());
}*/

/*
按照 key 对 T 进行 classifier 分组
使用自定义收集器 downstream 收集分组结果
public static <T, K, A, D>
Collector<T, ?, ConcurrentMap<K, D>> 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 <T, K, A, D, M extends ConcurrentMap<K, D>>
Collector<T, ?, M> groupingByConcurrent(Function<? super T, ? extends K> classifier,
Supplier<M> mapFactory,
Collector<? super T, A, D> downstream) {
Supplier<A> downstreamSupplier = downstream.supplier();
BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
BinaryOperator<ConcurrentMap<K, A>> merger = Collectors.<K, A, ConcurrentMap<K, A>>mapMerger(downstream.combiner());
@SuppressWarnings(“unchecked”)
Supplier<ConcurrentMap<K, A>> mangledFactory = (Supplier<ConcurrentMap<K, A>>) mapFactory;
BiConsumer<ConcurrentMap<K, A>, 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());
// 多个操作 –> 同时操作同一个结果容器 –> 同一时间,有且只有一个进行实际操作 –> 线程同步
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”)
Function<A, A> downstreamFinisher = (Function<A, A>) downstream.finisher();
Function<ConcurrentMap<K, A>, 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(“—————————————–\n”);

// 按性别分组 使用 ArrayList 进行 结果收集
ConcurrentMap<String, List<Student>> sexStudentConcurrent = students.stream()
.collect(Collectors.groupingByConcurrent(Student::getSex));
System.out.println(sexStudentConcurrent);
System.out.println(“—————————————–\n”);

// 使用自定义收集器 downstream 按性别分组 使用 HashSet 进行 结果收集
ConcurrentMap<String, HashSet<Student>> sexHashSetConcurrent = students.stream()
.collect(Collectors.groupingByConcurrent(Student::getSex, Collectors.toCollection(HashSet::new)));
System.out.println(sexHashSetConcurrent);
System.out.println(“—————————————–\n”);

// 使用自定义收集器 downstream 按性别分组 使用 HashSet 进行 结果收集 重置 CollectorImpl 实现
ConcurrentReferenceHashMap<String, HashSet<Student>> sexCustomCollectorImplConcurrent =
students.stream().collect(Collectors.groupingByConcurrent(Student::getSex,
ConcurrentReferenceHashMap::new, Collectors.toCollection(HashSet::new)));
System.out.println(sexCustomCollectorImplConcurrent);
System.out.println(“—————————————–\n”);
五、partitioningBy 分区
// 五、partitioningBy 分区

// 分区 partitioningBy

/*
对满足预期的条件 进行分区 使用 ArrayList 进行结果的收集
public static <T>
Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate) {
return partitioningBy(predicate, toList());
}*/

/*
对满足预期的条件 进行分区 使用自定义收集器 downstream 进行结果的收集
public static <T, D, A>
Collector<T, ?, Map<Boolean, D>> partitioningBy(Predicate<? super T> predicate,
Collector<? super T, A, D> downstream) {
BiConsumer<A, ? super T> downstreamAccumulator = downstream.accumulator();
BiConsumer<Partition<A>, T> accumulator = (result, t) ->
downstreamAccumulator.accept(predicate.test(t) ? result.forTrue : result.forFalse, t);
BinaryOperator<A> op = downstream.combiner();
BinaryOperator<Partition<A>> merger = (left, right) ->
new Partition<>(op.apply(left.forTrue, right.forTrue),
op.apply(left.forFalse, right.forFalse));
Supplier<Partition<A>> 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<Partition<A>, Map<Boolean, D>> 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(“—————————————–\n”);

// select * from students partition by (addr == Sword Art Online) ;
Map<Boolean, List<Student>> addrPartition = students.stream().collect
(Collectors.partitioningBy(student -> student.getAddr().equals(“Sword Art Online”)));
System.out.println(addrPartition);
System.out.println(“—————————————–\n”);

// 嵌套分区 先根据 sex 分区 再对结果按照 addr 进行分区
Map<Boolean, Map<Boolean, List<Student>>> 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(“—————————————–\n”);

// 使用自定义 downstream 收集器分区
Map<Boolean, HashSet<Student>> addrCustomPartition = students.stream().collect(Collectors.partitioningBy
(student -> student.getAddr().equals(“Sword Art Online”), Collectors.toCollection(HashSet::new)));
System.out.println(addrCustomPartition);
System.out.println(“—————————————–\n”);

}

}
六、测试结果
. ____ _ __ _ _
/\\ / ___’_ __ _ _(_)_ __ __ _ \ \ \ \
(()\___ | ‘_ | ‘_| | ‘_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| |) ) ) )
‘ |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: 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)]}
—————————————–

正文完
 0