【问题标题】:Group List Of Objects based on attributes populated根据填充的属性分组对象列表
【发布时间】:2019-06-18 09:11:59
【问题描述】:

我有一个有 10 个属性的类。我想根据是否填充的属性对该类的对象列表进行分组。准确地说,我会得到 2^n 个组。我可以迭代列表并编写 2^n 个条件并将它们分组到新列表中。有没有其他更好的方法来实现这个功能而不是编写那些开关条件?

【问题讨论】:

  • 十个二进制值不会导致 1024 个排列吗?您可以将其收集为位(每个字段都有自己的位),可以直接用作分组索引。

标签: java collections


【解决方案1】:

您可以避免编写多个 switch 语句,并在类本身中有一个标识符/键,这有助于了解是否设置了某些属性。

例子:

DemoClass(为简化起见3个属性)

public class DemoClass {
    public String property1 = null;
    public String property2 = null;
    public String property3 = null;

    public String getKey() {
        StringBuilder sb = new StringBuilder();
        sb.append(this.property1 != null ? "PROPERTY1" : "").append("|");
        sb.append(this.property2 != null ? "PROPERTY2" : "").append("|");
        sb.append(this.property3 != null ? "PROPERTY3" : "").append("|");

        return sb.toString();
    }
}

可以通过各种方式填充以上字段,例如overloaded constructorssetter 方法。

现在当你想分组时,你可以使用 HashMap 并根据它们的键值将类的对象添加到列表中,如下所示

Map<String, List<DemoClass>> map = new HashMap<>();
for (DemoClass demoClass : demoClasses) {
    map.computeIfAbsent(demoClass.getKey(), k -> new ArrayList<>()).add(demoClass);
}

【讨论】:

  • 好主意,但我认为不是computeIfAbsent,而是将每个demoClass 添加到值:map.put(demoClass.getKey(), demoClass.getOrDefault(demoClass.getKey(), new ArrayList&lt;&gt;())。另外,为什么不使用BitSet 作为密钥。
  • 我们不能使用demoClass 代替,因为它是DemoClass 的实例,而不是HashMap 的实例。此外,computeIfAbsent 是 Java 提供的一个很好的 API,与执行 getOrDefault 相比,它使代码更容易理解,如果值不是 Collection,这很有用
  • A BitSet 也可以使用,但我觉得上面的解决方案是使用提供有关设置属性的信息的字符串键的解决方案更具可读性,并且可以进一步扩展到用例,例如查找找出填充了哪些属性。
【解决方案2】:

我最终在一个字符串中获得了记录属性的位值(每个属性的 1 和 0(1 表示值存在,0 表示不存在))并按字符串分组。

records.stream().map(record -> new ExportDto.Builder().buildUpon(record).bitValue(getBitValueOfExportRecord(record)).build())
.collect(Collectors.groupingBy(ExportDto::getBitValue))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-08
    • 2023-02-07
    • 1970-01-01
    • 1970-01-01
    • 2023-04-11
    • 2020-02-04
    相关资源
    最近更新 更多