Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/333.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java:如何使用不同的equals定义执行列表操作?_Java_List_Comparator - Fatal编程技术网

Java:如何使用不同的equals定义执行列表操作?

Java:如何使用不同的equals定义执行列表操作?,java,list,comparator,Java,List,Comparator,Java:如何使用不同的equals定义执行列表操作 我有两个通用POJO列表。我需要根据比较列表中POJO的不同方式对列表执行一些set操作 例如,如果我的POJO具有以下结构: public class GenericPojo { private String id; private String address; private String city; private String country; private String extraDeta

Java:如何使用不同的equals定义执行列表操作

我有两个通用POJO列表。我需要根据比较列表中POJO的不同方式对列表执行一些set操作

例如,如果我的POJO具有以下结构:

public class GenericPojo {
    private String id;
    private String address;
    private String city;
    private String country;
    private String extraDetails;
}
(使用适当的getter和setter)

给定
List1
List2
,我将如何找到:

List1-List2(如果ID相等,
GenericPojo
类相等)

列表1和列表2相交(其中
id
地址
城市
国家
,但
通用POJO的
额外细节
不相等)


两个不同的自定义比较器类在这里有用吗?是否有任何库可以有效地处理这些操作,或者我应该尝试实现我自己的操作?

如果您的列表不包含重复项(使用假设的自定义比较器类的repsect),您可以使用两个树集,分别用两个比较器实例化


这种方法的一个缺点(除了复制约束)是,迭代元素时得到的顺序取决于比较器。

鉴于您对等式的具体要求,而且不适合您的需要,因此我认为您需要一个自定义实现来执行与这两个操作类似的操作。

没有一个解决方案符合列表契约,并且列表的现有实现都不允许您提供比较器。列表契约根据每个元素的
equals(Object)
方法定义列表的行为

如果比较器的
compare
方法与每个元素的
equals(Object)
方法不一致,则使用不同比较器的树集的建议也违反了合同


实际上,您可能需要实现自己的列表类。您可以使其成为一个不严格遵循列表契约的列表实现,但您需要注意,这不会破坏其他库方法/类。

如果您不想自己编程设置操作,也不介意浪费一些CPU和内存资源,您可以:

  • 基于您的
    GenericPojo
    s构建
    WrappedPojo
    s
  • 给出
    WrappedPojo
    适当的
    equals()实现
  • 创建适当类型的
    WrappedPojo
    的新列表,以便对其执行操作
  • 操作完成后,将包含的
    GenericPojo
    s复制回其原始容器(如果需要)

丑陋但简单。

您可以通过以下方法将所有这些保留在域对象中:

  • 仅基于
    id
    GenericPojo
    上实现
    等于(
  • 根据附加的
    GenericPojo
    字段,将
    WrappedPojo
    定义为
    GenericPojo
    的包装,并使用
    等于(
  • 对于第二个用例,使用包装实例的列表

  • 我建议根本问题是试图拥有一个具有不同相等定义的单一域类。

    如果您必须在无法控制的情况下操纵类,我建议使用委托。以下是我的尝试:

  • 创建一个
    RichList
    包装器,围绕
    List
    s,基于
  • 创建一个
    EqualityChecker
    interface,使用一个方法“publicbooleanequal(t1,T,t2)”
  • 为通用pojo实现此接口两次:一次只检查ID,另一次检查其他字段
  • 添加您感兴趣的两种方法(set substraction和set intersection),但添加一个补充参数,即
    EqualityChecker
    将为您执行相等测试的具体实例
  • 因此,您可以将这两个操作添加到任何类型对象的所有现有
    列表
    s中,您已经为这些对象编写了
    EqualityChecker


    进一步的改进:您还可以编写一个默认的
    EqualityChecker
    ,它只调用比较对象的equals方法。然后,您可以重载这两个新操作,以默认
    EqualityChecker

    您尝试执行的两个操作都是功能性的,尽管Java不太支持这些操作,您可能会以非常不同的方式编写它们。 为了适应java,您可能需要重新思考您试图实现的目标

    您所做的是对数据类型的投影执行操作(即,对于字段子集)

    您正在使用的操作也是设置操作,而不是列表操作。e、 g.您不能将两个列表相交(或者至少您必须定义这意味着什么),Remove也可能无法完全按照您对列表的预期执行

    假设您有一个方法,它返回一个POJO集合,其中只包含您指定的字段。过去,我编写了一个库来高效地使用动态生成的类来实现这一点,看看functional Java或类似的东西

    public static <Pojo, Pojo2> Set<Pojo2> project(Collection<Pojo> collection,
          String... fieldsToRetain);
    
    公共静态集项目(集合,
    字符串…字段存储);
    
    List1-List2(其中,如果ID相等,则GenericPojo类相等)

    Set setOfIds=project(列表1,“id”)
    项目(列表2,“id”);
    
    列表1和列表2的交集(其中id、地址、城市、国家,但不包括GenericPojo的额外详细信息)

    Set intersection=项目(列表1,“id”、“地址”、“城市”、“国家”);
    交叉口保留(项目(列表2,“id”、“地址”、“城市”、“国家”);
    
    这是我的第一个问题,如果我有任何风格错误或其他错误,请编辑并让我知道我做了什么
    Set<PojoWithId> setOfIds = project(list1, "id")
    setOfIds.retainAll(project(list2, "id"));
    
    Set<PojoWithThreeFields> intersection = project(list1, "id", "address", "city", "country");
    intersection.retainAll(project(list2, "id", "address", "city", "country"));