java 根据条件合并列表中的项目

64jmpszr  于 2022-12-21  发布在  Java
关注(0)|答案(1)|浏览(137)

我有一个自定义对象的列表:

public class CustomObject {

    protected String field1;
    protected String field2;
    protected String field3;
    protected List<String> listOfString;
} 

List<CustomObject> list = new ArrayList<>();
CustomObject customObject1 = new CustomObject("1234", "", "", Arrays.asList("a", "b"));
CustomObject customObject2 = new CustomObject("1234", "", "notblank", Arrays.asList("c", "d"));

CustomObject customObject3 = new CustomObject("", "1234", "", Arrays.asList("a", "b"));
CustomObject customObject4 = new CustomObject("", "1234", "notblank", Arrays.asList("c", "d"));

list.add(customObject1);
list.add(customObject2);
list.add(customObject3);
list.add(customObject4);

我想应用一个自定义方法来合并列表中的两个项目,并比较每个项目。例如,在列表中迭代,如果customObject1.getField1()等于customObject2.getField1(),我想应用我的merge函数。
在我的示例中,customObject1应该与customObject2合并,customObject3应该与customObject4合并,因为它们具有相同的field1或相同的field2。
顺便说一句,我的合并函数包括将具有空白“field3”的customObject的“listOfString”添加到具有填充“field3”的customObject中。
我的merge函数是将listOfString保留在具有空白字段3的自定义对象中。该listOfString将被添加到另一个自定义对象的listOfString中,该自定义对象将被合并为一个。例如,如果cutomObject1和customObject2被合并为一个,我们应该具有以下内容:

public class CustomObject {

    protected String field1; = "1234"
    protected String field2; = ""
    protected String field3; = "notblank"
    protected List<String> listOfString; = ["a", "b", "c", "d"]
}

我使用Collectors.toMap()成功地完成了这一操作,但当我只比较field1时:

Map<List<String>, CustomObject> map = myList.stream()
        .collect(
                Collectors.toMap(customObject -> customObject.getField1(),
                        individu -> individu, this::customMergeMethod));

但我的问题是:如果customObject1.getField1()等于customObject2.getField1()如果customObject1.getField2()等于customObject2.getField2(),我想合并项目。我认为在这种情况下不可能使用Collectors.toMap()。
我应该用什么来修复这个?谢谢
我试着使用一个带有重写的比较方法的集合,但是如果可能的话,如何使用我的自定义合并方法呢?

Set<CustomObject> s = new TreeSet<CustomObject>(new Comparator<CustomObject>() {

    @Override
    public int compare(CustomObject customObject1, CustomObject customObject2) {
        [...]
        return 0;
    }
});
5ssjco0h

5ssjco0h1#

看起来像是另一个问题“我如何使用流实现XYZ,尽管使用普通循环会更容易”
但是,您可以引入一个新的CustomKey类(我使用一个记录来获取equals/hashCode)来保存CustomObject的组合键,以便在Collectors.toMap中使用:

public record CustomKey(String field1, String field2) {};

Map<CustomKey, CustomObject> map = myList.stream()
        .collect(Collectors.toMap(
              o -> new CustomKey(o.field1, o.field2),
              Function.identity(),
              this::customMergeMethod)
         );

如果您对何时合并两个项有其他/额外/更复杂的要求,请覆盖CustomKey的hashCode/equals,并在这些方法中实现这些要求。

  • UPDATE*:给定注解中的代码片段,CustomKey类可能如下所示:
public class CustomKey {
    String field1; String field2;
    
    @Override
    public boolean equals(Object obj) {
        
        if (obj == this) {
            return true;
        }
        
        if (obj == null) {
            return false;
        }
        
        if (!obj.getClass().equals(this.getClass())) {
            return false;
        }
        
        final CustomKey otherKey = (CustomKey)obj;
        
        final String thisKeyValue = StringUtils.defaultIfBlank(this.field1, StringUtils.defaultIfBlank(this.field2, ""));
        final String otherKeyValue = StringUtils.defaultIfBlank(otherKey.field1, StringUtils.defaultIfBlank(otherKey.field2, ""));
        
        return Objects.equals(thisKeyValue, otherKeyValue);
    }
};

你应该注意到,在这个实现中,如果this有一个非空的field1,而obj只有field2,你将比较field1field2的值。

相关问题