【问题标题】:Filter List<Object[]> to retain consistent values过滤 List<Object[]> 以保留一致的值
【发布时间】:2015-08-03 12:14:51
【问题描述】:

首先,我有一个包含多个 Object 类型数组的列表,例如:

    Object[] arr1 = new Object[] {"FIM4R1500030", BigInteger.valueOf(5272456l), "A10328E00074531842"};
    Object[] arr2 = new Object[] {"FIM4R1500031", BigInteger.valueOf(886445384123l), "A10328E00074531842"};
    final List<Object[]> arrs = Arrays.asList(arr1, arr2);

然后,我编写了一个逻辑来过滤它们以保留一致的值并为不一致的值填充 null。结果看起来像这样:

List[
  Object[][null,null,"A10328E00074531842"],
  Object[][null,null,"A10328E00074531842"]
]

现在,我的问题是这个逻辑相当复杂且难以阅读,我不确定我是否可以接受它。此外,我真的不想开始编写一个成熟的实用程序类,因为它的功能似乎很小。这是我的代码:

    final Predicate<Integer> isConsistant = index -> {

        for (Object[] arr : arrs) {
            if (!arr[index].equals(arrs.get(0)[index])) {
                return false;
            }
        }
        return true;
    };

    List<Object[]> filtered = arrs.stream().map(arr -> {

        Object[] returnList = new Object[arrs.get(0).length];

        for (int i = 0; i < arrs.get(0).length; i++) {
            if (isConsistant.test(i)) {
                returnList[i] = arrs.get(0)[i];
            } else {
                returnList[i] = null;
            }
        }

        return returnList;
    })
            .collect(toList());

我的问题是,如何让这更简单!

【问题讨论】:

  • “如何让这个更简单!” codereview.stackexchange.com?
  • 对于初学者来说,将这些东西转储到异构对象数组而不是适当的类中,无论如何都会让你的代码变得一团糟。
  • @LouisWasserman 同意了 - 但遗憾的是,这是 Hibernate 让我使用的。

标签: java arrays java-8 java-stream


【解决方案1】:

您为什么想要List&lt;Object[]&gt; 作为过滤器的结果?如果我很好地理解了您的问题,那么该列表中的所有Object[] 看起来都一样。所以代码可能只是:

Object[] filtered = IntStream.range(0, arrs.get(0).length)
            .mapToObj(i -> arrs.stream().allMatch(arr -> arr[i] != null && arr[i].equals(arrs.get(0)[i])) ? arrs.get(0)[i] : null)
            .toArray();

【讨论】:

    【解决方案2】:

    这段代码的问题不是它太复杂,而是它不必要地慢:对于arrs 中的每一对(row, column),你再次遍历整个数组,试图确定@987654323 中的所有值是否@ 彼此相等。本质上,您在同一列 N 上运行 isConsistant 次 - 每行一次,即使谓词始终返回相同的值。当行数很高时,这可能非常重要。

    该过程总是以N 相同的行结束,因此您不妨构造该行一次,然后复制它的N

    Object[] row = new Object[arrs.get(0).length];
    for (int i = 0 ; i != arrs.get(0).length ; i++) {
        if (isConsistant.test(i)) {
            row[i] = arrs.get(0)[i];
        }
    }
    // Now we make N copies of that row:
    List<Object[]> filtered = new ArrayList<Object[]>();
    for (int i = 0 ; i != arrs.length() ; i++) {
        filtered.add((Object[])row.clone());
    }
    

    如果您不打算修改filtered 的元素,您可以跳过clone 部分,并插入相同的对象N 次。

    【讨论】:

    • 它同意我的代码中有一个循环迭代太多 - 感谢您发现它!此外,限制流的使用是正确的,因为它们不会增加可读性。不过,我觉得它的代码太多了。
    • @FritzDuchardt 您始终可以将下半部分重写为流generate+limit 以使该部分成为单行。我确信顶部部分也可以用流重写,但我认为与当前的植入相比,可读性会受到影响。将构造row 的代码也与isConsistant 合并可能是个好主意,这样整个代码会变得更短。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-07
    • 1970-01-01
    • 2011-11-18
    • 2020-02-13
    • 2021-02-21
    相关资源
    最近更新 更多