Collectors.toMap中的合并函数上的线程“ main”中的异常java.lang.UnsupportedOperationException

时间:2019-03-12 13:42:37

标签: java java-stream

我有自己的本地对象StudentInGroup流(请参见下文),我想用3种几乎相同的方式将其放入地图中。由于某些原因,其中有两个成功,而最后一个引发了异常:

Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractCollection.add(AbstractCollection.java:262)
at java.util.AbstractCollection.addAll(AbstractCollection.java:344)
at containers.streams.StreamsTest3.lambda$main$13(StreamsTest3.java:93)
at java.util.HashMap.merge(HashMap.java:1245)
at java.util.stream.Collectors.lambda$toMap$172(Collectors.java:1320)
at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1374)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:481)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
at containers.streams.StreamsTest3.main(StreamsTest3.java:91)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)

所以对象是:

import java.util.Optional;

public class StudentInGroup {

    private Optional<String> groupNumber;
    private String name;
    private boolean isGirl;
    private int age;

    @Override
    public String toString() {
        return "StudentInGroup{" +
                "groupNumber=" + groupNumber +
                ", name='" + name + '\'' +
                ", isGirl=" + isGirl +
                ", age=" + age +
                '}';
    }

    public StudentInGroup(String name, String groupNumber, int age, boolean isGirl)
    {
        this.name=name;
        this.groupNumber=Optional.ofNullable(groupNumber);
        this.age=age;
        this.isGirl=isGirl;
    }

    public Optional<String> getGroupNumber() {
        return groupNumber;
    }

    public void setGroupNumber(Optional<String> groupNumber) {
        this.groupNumber = groupNumber;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isGirl() {
        return isGirl;
    }

    public void setGirl(boolean girl) {
        isGirl = girl;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

如果这样创建流:

    Optional<StudentInGroup> petrov = Optional.of(new StudentInGroup("Petrov", null, 18, false));
    Optional<StudentInGroup> petrova = Optional.of(new StudentInGroup("Petrova", "11-305", 18, true));

    List<Optional<StudentInGroup>> studentInGroupList = new ArrayList<>();
    studentInGroupList.add(Optional.of(new StudentInGroup("Ivanov", "11-307", 18, false)));
    studentInGroupList.add(Optional.of(new StudentInGroup("Johns", "11-307", 19, false)));
    studentInGroupList.add(Optional.of(new StudentInGroup("Walitov", "11-307", 17, false)));
    studentInGroupList.add(Optional.of(new StudentInGroup("Kowalski", "11-302", 19, false)));
    studentInGroupList.add(Optional.of(new StudentInGroup("Glauberová", "11-302", 19, true)));
    studentInGroupList.add(Optional.of(new StudentInGroup("Dybenko", "11-307", 17, true)));
    studentInGroupList.add(Optional.of(new StudentInGroup("Ishikawa", "11-305", 18, false)));
    studentInGroupList.add(Optional.of(new StudentInGroup("Nguyen", "11-305", 18, false)));
    studentInGroupList.add(Optional.of(new StudentInGroup("Chui", "11-305", 18, true)));
    studentInGroupList.add(petrov);
    studentInGroupList.add(Optional.empty());
    studentInGroupList.add(petrova);
Supplier<Stream<StudentInGroup>> studentInGroupStreamSupplier = () -> studentInGroupList.stream().map((o) -> o.orElse(new StudentInGroup(null, null, -1, false)));

和两种工作方法是

  Map<Integer, Set<StudentInGroup>> stringStudentInGroupMap3 = studentInGroupStreamSupplier.<StudentInGroup>get().collect(Collectors.toMap(StudentInGroup::getAge, Collections::<StudentInGroup>singleton,
            (Set<StudentInGroup> a, Set<StudentInGroup> b) -> {
                Set<StudentInGroup> studentInGroupSet = new HashSet<>();
                studentInGroupSet.addAll(a);
                studentInGroupSet.addAll(b);
                return studentInGroupSet;
            }));
    System.out.println(stringStudentInGroupMap3);


    Map<Integer, Set<StudentInGroup>> stringStudentInGroupMap4 = studentInGroupStreamSupplier.<StudentInGroup>get().collect(Collectors.toMap(StudentInGroup::getAge, x -> new HashSet<>(Arrays.asList(x)),
            (x, y) -> {
                x.addAll(y);
                return x;
            }));
    System.out.println(stringStudentInGroupMap4);

输出值为

{-1=[StudentInGroup{groupNumber=Optional.empty, name='null', isGirl=false, age=-1}], 17=[StudentInGroup{groupNumber=Optional[11-307], name='Dybenko', isGirl=true, age=17}, StudentInGroup{groupNumber=Optional[11-307], name='Walitov', isGirl=false, age=17}], 18=[StudentInGroup{groupNumber=Optional[11-307], name='Ivanov', isGirl=false, age=18}, StudentInGroup{groupNumber=Optional.empty, name='Petrov', isGirl=false, age=18}, StudentInGroup{groupNumber=Optional[11-305], name='Petrova', isGirl=true, age=18}, StudentInGroup{groupNumber=Optional[11-305], name='Nguyen', isGirl=false, age=18}, StudentInGroup{groupNumber=Optional[11-305], name='Ishikawa', isGirl=false, age=18}, StudentInGroup{groupNumber=Optional[11-305], name='Chui', isGirl=true, age=18}], 19=[StudentInGroup{groupNumber=Optional[11-302], name='Kowalski', isGirl=false, age=19}, StudentInGroup{groupNumber=Optional[11-302], name='Glauberová', isGirl=true, age=19}, StudentInGroup{groupNumber=Optional[11-307], name='Johns', isGirl=false, age=19}]}

{-1=[StudentInGroup{groupNumber=Optional.empty, name='null', isGirl=false, age=-1}], 17=[StudentInGroup{groupNumber=Optional[11-307], name='Dybenko', isGirl=true, age=17}, StudentInGroup{groupNumber=Optional[11-307], name='Walitov', isGirl=false, age=17}], 18=[StudentInGroup{groupNumber=Optional[11-307], name='Ivanov', isGirl=false, age=18}, StudentInGroup{groupNumber=Optional.empty, name='Petrov', isGirl=false, age=18}, StudentInGroup{groupNumber=Optional[11-305], name='Petrova', isGirl=true, age=18}, StudentInGroup{groupNumber=Optional[11-305], name='Nguyen', isGirl=false, age=18}, StudentInGroup{groupNumber=Optional[11-305], name='Ishikawa', isGirl=false, age=18}, StudentInGroup{groupNumber=Optional[11-305], name='Chui', isGirl=true, age=18}], 19=[StudentInGroup{groupNumber=Optional[11-302], name='Kowalski', isGirl=false, age=19}, StudentInGroup{groupNumber=Optional[11-302], name='Glauberová', isGirl=true, age=19}, StudentInGroup{groupNumber=Optional[11-307], name='Johns', isGirl=false, age=19}]}

此调用导致上述错误:

Map<Integer, Set<StudentInGroup>> stringStudentInGroupMap6 = studentInGroupStreamSupplier.<StudentInGroup>get().collect(Collectors.toMap(StudentInGroup::getAge, Collections::<StudentInGroup>singleton,
            (x, y) -> {
                x.addAll(y);
                return x;
            }));
    System.out.println(stringStudentInGroupMap6);

那么,在这种情况下抛出UnsupportedOperationException的原因是什么?

PS。我知道groupingBy是最好的方法,问题是为什么会引发异常。

1 个答案:

答案 0 :(得分:5)

Collections.singleton*()方法返回不可变的Collection实现。

所以您必须替换:

Collections::<StudentInGroup>singleton

使用:

HashSet::new

或适合您需求的Set实现。