在Java中是否有一种简单的方法可以使用自定义equals函数来获取两个集合之间的差异而不会覆盖equals?

Fre*_*tin 5 java collections java-8 java-stream

我愿意使用lib.我只是想要一些简单的东西来区分两个集合,而不是正常的equals函数.

现在我使用类似的东西:

collection1.stream()
           .filter(element -> !collection2.stream()
                                          .anyMatch(element2 -> element2.equalsWithoutSomeField(element)))
           .collect(Collectors.toSet());
Run Code Online (Sandbox Code Playgroud)

我想要的是:

Collections.diff(collection1, collection2, Foo::equalsWithoutSomeField);
Run Code Online (Sandbox Code Playgroud)

(编辑)更多背景:

应该提到我正在寻找已存在的东西而不是自己编码.如果不存在,我可能会根据您的想法编写一个小的工具.

此外,在我的情况下,Real复制是不可能的:集合是集合.但是,根据自定义等于的重复项是可能的,不应通过此操作删除.它似乎是很多可能的解决方案的限制.

Nik*_*kar 3

您可以使用UnifiedSetWithHashingStrategyEclipse CollectionsUnifiedSetWithHashingStrategy允许您使用自定义创建一个集合HashingStrategyHashingStrategy允许用户使用自定义hashCode()equals(). 对象的hashCode()equals()未被使用。

根据OP的要求通过评论进行编辑

您可以根据您的要求使用reject()或。removeIf()

代码示例:

// Common code
Person person1 = new Person("A", "A");
Person person2 = new Person("B", "B");
Person person3 = new Person("C", "A");
Person person4 = new Person("A", "D");
Person person5 = new Person("E", "E");

MutableSet<Person> personSet1 = Sets.mutable.with(person1, person2, person3);
MutableSet<Person> personSet2 = Sets.mutable.with(person2, person4, person5);

HashingStrategy<Person> hashingStrategy =
    HashingStrategies.fromFunction(Person::getLastName);
Run Code Online (Sandbox Code Playgroud)

1)使用reject():创建一个新的,其中包含所有不满足Set元素。Predicate

@Test
public void reject()
{
    MutableSet<Person> personHashingStrategySet = HashingStrategySets.mutable.withAll(
        hashingStrategy, personSet2);

    // reject creates a new copy
    MutableSet<Person> rejectSet = personSet1.reject(personHashingStrategySet::contains);
    Assert.assertEquals(Sets.mutable.with(person1, person3), rejectSet);
}
Run Code Online (Sandbox Code Playgroud)

2) 使用:通过删除满足 的元素来removeIf()改变原始数据。SetPredicate

@Test
public void removeIfTest()
{
    MutableSet<Person> personHashingStrategySet = HashingStrategySets.mutable.withAll(
        hashingStrategy, personSet2);

    // removeIf mutates the personSet1
    personSet1.removeIf(personHashingStrategySet::contains);
    Assert.assertEquals(Sets.mutable.with(person1, person3), personSet1);
}
Run Code Online (Sandbox Code Playgroud)

通过评论回答 OP 的要求:如果其他人可能觉得有用,请保留以供参考。

3) 使用Sets.differenceInto()Eclipse Collections 中提供的 API:

在下面的代码中,set1和是使用和 的两个set2集合。the是一个so,它使用the来定义唯一性。因此,尽管does not contains但它具有与contains only相同的姓氏。Personequals()hashCode()differenceSetUnifiedSetWithHashingStrategylastNameHashingStrategyset2person3person1differenceSetperson1

@Test
public void differenceTest()
{
    MutableSet<Person> differenceSet = Sets.differenceInto(
        HashingStrategySets.mutable.with(hashingStrategy), 
        set1, 
        set2);

    Assert.assertEquals(Sets.mutable.with(person1), differenceSet);
}
Run Code Online (Sandbox Code Playgroud)

两个代码块共有的 Person 类:

public class Person
{
    private final String firstName;
    private final String lastName;

    public Person(String firstName, String lastName)
    {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public String getFirstName()
    {
        return firstName;
    }

    public String getLastName()
    {
        return lastName;
    }

    @Override
    public boolean equals(Object o)
    {
        if (this == o)
        {
            return true;
        }
        if (o == null || getClass() != o.getClass())
        {
            return false;
        }
        Person person = (Person) o;
        return Objects.equals(firstName, person.firstName) &&
                Objects.equals(lastName, person.lastName);
    }

    @Override
    public int hashCode()
    {
        return Objects.hash(firstName, lastName);
    }
}
Run Code Online (Sandbox Code Playgroud)

Javadoc: MutableSetUnifiedSetUnifiedSetWithHashingStrategyHashingStrategySetsrejectremoveIf

注意:我是 Eclipse Collections 的提交者