I have the below code, when i remove an item from a Set using remove
or removeIf
, a get an error 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) at com.xxxx.updateSpeciality(EstablishmentAggregate.java:916) at com.xxxx.EstablishmentAggregate.on(EstablishmentAggregate.java:909) 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:498)
CodePudding user response:
Are you sure that specialities is an HashSet
? Can be created somewhere as a different type? The UnsupportedOperationException
can be thrown on an unmodifiable set for example.
It seems that somewhere you can set the specialities
with an explicit setSpecialities
passing an object that is a Set
, but not an HashSet
.
In this case there are classes instantiating Set that doesn't support the remove
and removeIf
methods and their implementation is something like the following code:
public boolean remove(Object o) {
throw new UnsupportedOperationException();
}
A way to create an unmodifiable Set is for example using the function of java 9 Set.of
:
Returns an immutable set containing zero elements
And as explained in the javadoc:
The
Set.of()
static factory methods provide a convenient way to create immutable sets. The Set instances created by these methods have the following characteristics:
- They are structurally immutable. Elements cannot be added or removed. Calling any mutator method will always cause UnsupportedOperationException to be thrown. However, if the contained elements are themselves mutable, this may cause the Set to behave inconsistently or its contents to appear to change.
CodePudding user response:
Here's how I would update or add an entry in the set.
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);
}
}