【问题标题】:HashSet throws UnsupportedOperationExceptionHashSet 抛出 UnsupportedOperationException
【发布时间】:2022-01-22 23:14:46
【问题描述】:

我有下面的代码,当我使用remove removeIf 从集合中删除一个项目时,得到一个错误java.lang.UnsupportedOperationException: null

private Set<Speciality> specialities = new HashSet<>();

private void updateSpeciality(SpecialityETAUpdatedEvent evt) {
    if (CollectionUtils.isNotEmpty(this.specialities)) {
        Optional<Speciality> specialityOptional = this.specialities.stream().filter((Speciality speciality) -> speciality.getCode().equals(evt.code)).findFirst();
        if (specialityOptional.isPresent()) {
            this.specialities.remove(specialityOptional.get());// **** Exception thrown here
        }
    }
    this.specialities.add(new Speciality().code(evt.code).label(evt.label).startDate(evt.startDate));
}

java.lang.UnsupportedOperationException: null at java.util.Collections$UnmodifiableCollection.remove(Collections.java:1060) 在 com.xxxx.updateSpeciality(EstablishmentAggregate.java:916) 在 com.xxxx.EstablishmentAggregate.on(EstablishmentAggregate.java:909) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:498)

【问题讨论】:

  • 请参阅minimal reproducible example。您需要使您的代码示例成为我们可以复制/粘贴、运行和观察与您相同的结果;否则我们无法找出导致问题的原因。
  • 您需要提供堆栈跟踪。
  • 解释在你的调用栈中:你的集合是UnmodifiableCollection;不是HashSet。你给specialities分配了什么?
  • 我想知道堆栈跟踪中的“UnmodifiableCollection”...这可能与在发布的代码中创建的 Set 不同 - 包含 minimal reproducible example 的一个原因(例如, Set.of(...)返回这样一个不可修改的集合)

标签: java stream set hashset


【解决方案1】:

您确定专业是HashSet 吗?可以在某处创建为不同的类型吗?例如,UnsupportedOperationException 可以扔到不可修改的集合上。

您似乎可以在某处设置specialities,并使用显式setSpecialities 传递一个Set,但不是HashSet

在这种情况下,实例化 Set 的类不支持 removeremoveIf 方法,它们的实现类似于以下代码:

public boolean remove(Object o) {
   throw new UnsupportedOperationException();
}

一种创建不可修改Set的方法是例如使用java 9 Set.of的函数:

返回一个不可变集合包含零个元素

正如 javadoc 中所解释的:

Set.of() 静态工厂方法提供了一种创建不可变集合的便捷方式。这些方法创建的 Set 实例具有以下特点:

  • 它们在结构上是不可变的。不能添加或删除元素。 调用任何 mutator 方法总是会导致抛出 UnsupportedOperationException。但是,如果包含的元素本身是可变的,这可能会导致 Set 行为不一致或其内容似乎发生变化。

【讨论】:

  • 实际的documentation 更加严格:“它们不可修改。”不仅“结构上不可变”(因为没有索引访问或任何其他更改元素的方法,这并不重要:-))
【解决方案2】:

以下是我将如何在集合中更新或添加条目。

import java.util.*;
class Record {
    int id, val;
    Record(int id) { this.id = id; }
    Record(int id, int val) { this.id = id; this.val=val;}
  
    public boolean equals(Object o){
        return o instanceof Record ? id==((Record)o).id : false;
    }
    public int hashCode() {  
        return Objects.hashCode(id);
    }
    public String toString(){
        return String.format("Container[id=%d, val=%d]", id, val);
    }
}

class RecordSet extends HashSet<Record> {
    Record addOrUpdate(Record c){
        remove(c);
        add(c);
        return c;
    }
}

public class Main {
    public static void main(String[] args) {
        RecordSet set = new RecordSet();
        set.add(new Record(1,100));
        set.add(new Record(2,200));
        set.add(new Record(3,300));
        
        System.out.println("Before: " + set);
        
        Record c1 = new Record(1,500);  //update existing record
        Record c2 = new Record(4,400);  //new record
        
        set.addOrUpdate(c1);
        set.addOrUpdate(c2);
        
        System.out.println("After: " + set);
    }
}

【讨论】:

    猜你喜欢
    • 2013-02-26
    • 2014-01-30
    • 1970-01-01
    • 1970-01-01
    • 2016-02-24
    • 2014-09-13
    • 2011-11-05
    • 2014-11-28
    • 2014-09-21
    相关资源
    最近更新 更多