简体   繁体   中英

Set::removeIf with true predicate does not delete elements

I have a quite simple problem, yet a very weird behaviour on which a Set does not delete elements on true predicates for some reason.

The entities (for reference only, as this does not have anything to do with the set item - or shouldn't):

@Data
@MappedSuperclass
@EqualsAndHashCode(of = "uuid")
public abstract class Model<ID> {

    @Id
    @GeneratedValue
    protected ID id;

    protected UUID uuid; // Hybrid model

    @PrePersist
    private void onPersisting() {
        uuid = UUID.randomUUID();
    }

}

@Data
@Entity
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true, of = "name")
@Table(uniqueConstraints = @UniqueConstraint(name = "scope_name", columnNames = "name"))
public class Scope extends Model<Long> {

    private String name;

    public Scope(UUID uuid) {
        this.uuid = uuid;
    }

    public Scope(String name) {
        this.name = name;
    }

}

@Data
@Entity
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true, of = "name")
@Table(uniqueConstraints = @UniqueConstraint(name = "role_name", columnNames = "name"))
public class Role extends Model<Long> {

    private String name;

    @ManyToMany(cascade = { CascadeType.PERSIST, CascadeType.MERGE })
    @JoinTable(name = "role_scopes", joinColumns = @JoinColumn(name = "role_id"), inverseJoinColumns = @JoinColumn(name = "scope_id"))
    private Set<Scope> scopes = new HashSet<>();

    public Role(UUID uuid, Scope... scopes) {
        this.scopes = Stream.of(scopes).collect(Collectors.toSet());
        this.uuid = uuid;
    }

    public Role(String name, Scope... scopes) {
        this.scopes = Stream.of(scopes).collect(Collectors.toSet());
        this.name = name;
    }

}

The following snippet, called within a JUnit test case, does not delete the set elements (simplified for readability):

@Transactional
public Role create(Role role) {
    role.getScopes().removeIf(unused -> true); // <----
    return role;
}

For some reason, that snippet does work:

Set<String> strings = new HashSet<>();
strings.add("FOO");
strings.add("BAR");
strings.removeIf(unused -> true);

What's going on here?

It is because of overridden equals and hashCode that is done by @Data annotation on your Scope class. If you remove it or replace with @Getter @Setter it will work

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM