Java - 消除3D对象数组中的重复项

时间:2016-02-14 03:25:03

标签: java arrays multidimensional-array duplicates

我有

 Array<Array<Array<CustomObject>>> 

我需要消除重复的

Array<Array<CustomObject>>

数组中的顺序并不重要,所以我不通过索引进行比较,我比较了数组中的元素。最终结果需要保持3D数组格式。因此,我不需要将阵列展平为只有一个大阵列。

我认为它可能有所帮助的一种方法是对数组进行排序。 我必须像这样对数组进行排序:

  • 最嵌套的(1D)数组(Array<CustomObject>) - &gt;按名称字母顺序

  • 下一个(2D)数组(Array<Array<CustomObject>>) - &gt;字母顺序,但只是最嵌套(1D)数组的第一个元素(Array<CustomObject>

  • 最外层(3D)数组(Array<Array<Array<CustomObject>>>)按2D数组的大小排序(Array<Array<CustomObject>>

通过这三种方法,副本应该紧挨着另一种方法,但我不知道如何消除它们而不创建太多嵌套循环来比较元素。

当前实现的输出示例:

[[v1],[v2,v3]]

[[v1,v2],[v3]]

[[v1,v2],[v3]]

[[v1,v2],[v2,v3]]

[[v1],[v2,v3]]

[[v1,v2],[v2,v3]]

[[v1],[v2],[v3]]

[[v1],[v2],[v3]]

[[v1],[v2],[v3]]

[[v1],[v2],[v3]]

[[v1],[v2],[v3]]

[[v1],[v2],[v3]]

我已经尝试过使用Arrays.equal和deepequal但它给出了一个错误,指出该方法不能应用于我的CustomObjects数组。

CustomObjects类实现了Comparable,我重写了equals,hashCode和compareTo。

欢迎任何建议。谢谢!

3 个答案:

答案 0 :(得分:2)

你必须找到一个快速回答问题“它们是不同的”。

if x.length != y.length then they are different

快速而干净的答案。因此,按大小排序的想法非常好。

我们可以制作另一个“简单”字段来快速回答“不同”吗?是的,让我们计算每个哈希码并比较它们。如果哈希码不同 - &gt;对象是不同的。

要计算一个哈希码,我们可以使用https://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html#deepHashCode(java.lang.Object[]) ..但是如果数组中的顺序不重要,它会破坏你的情况,[a,b,c] == [b,a,c] case,但是会有来自deepHashCode的不同结果。

要对抗它 - 在使用deepHashCode之前对数组元素进行排序。

所以:

  • 对所有L1阵列进行排序,
  • 对所有L2数组进行排序(我认为你不应该停留在比较器的第一个元素上)
  • 制作Map [Integer,List [Element]]并为每个L3 deepHashCode填充它 - &gt;列表[L3]

后来迭代:

List<Element> result = ...

for (List<Element> l : map.values()) {
   if ( l.size() > 1 ) {
       final Iterator i = l.iterator();
       Element head = i.next();
       while (i.hasNext()) {
          Element cur = i.next();
          if (comparator.compare(head,cur) == 0) {
             i.remove();
          }
          head = cur;
       }
   }
   result.addAll(l);
 }
 return result.toArray(..);

答案 1 :(得分:2)

如果您只是寻找不同的元素,一个简单的方法是展平3D数组。在Java-8中,您可以使用以下方法将3D数组展平为Stream<CustomObject>

public static Stream<Object> flatten(Object[][][] arr){
    return Arrays.stream(arr).parallel()
    .flatMap(Arrays::stream)
    .flatMap(Arrays::stream);
}

然后简单地致电:

 CustomObject[] noDupes = flatten(arr).distinct().toArray();

编辑:如果您使用的是较早的JVM并且可以使用1D阵列,请使用Set删除重复项:

public <T> T[] distinct(T[][][] arr){
    Set<T> noDupes = new HashSet<>();

    for(T[][] oll: arr){
        for(T[] ol: oll){
            noDupes.addAll(Arrays.asList(ol));
        }
    }
    return (T[]) noDupes.toArray();
}

答案 2 :(得分:-2)

您是否尝试过使用Collections类List,它不允许重复?或ArrayList,它允许重复并且具有测试是否相等的方法?