Java从List<List<float[]>>中删除重复项

3

我正在尝试删除在 List<List<float[]>> 中找到的重复记录。我尝试使用不允许重复的集合(HashList),但我无法弄清楚如何正确地进行转换。为了循环遍历所有元素,我将执行以下操作。

List<List<float[]>> tmp; 

for(int i=0; i<tmp.get(0).size();i++){
    System.out.println(java.util.Arrays.toString(tmp.get(0).get(i)));
}

我想从列表中移除它们。因此,所有在 tmp.get(0).get(这里需要移除的元素) 找到的元素都将被移除。
tmp.get(0).get(1) =[-70.89,42.12]

tmp.get(0).get(2) =[-70.89,42.12]

我希望删除 tmp.get(0).get(2)

当前的实现方式,只在存在 1 个重复时有效,而在存在多个重复时无效。

for(int i=0; i<old.get(0).size();i++){
            if(i == old.get(0).size()-1){
                System.out.println("max size");
                return old;
            }
            else if(Arrays.toString(old.get(0).get(i)).equalsIgnoreCase(Arrays.toString(old.get(0).get(i+1)))){
                old.get(0).remove(i);
                i++;
            } else {
            i++;
            }

4
你想要从整个列表中删除重复项还是从内部包含的列表中删除? - arshajii
你想要移除重复的 List<float[]> 吗? - Sotirios Delimanolis
1
相关:Java中的equals vs Arrays.equals - Paul Bellora
1
你可以提供一些示例输入和输出,以便清楚地说明这个程序应该做什么。 - millimoose
1
那么,如果存在两个具有相同元素的数组,则应删除其中一个数组。但是,如果两个数组共享单个公共值,则不应删除该值?请澄清。 - John B
显示剩余3条评论
3个回答

3

如果我理解正确,您正在寻找Set<List<float[]>>


我已经更新了问题,并添加了一些实现。 - user2524908
是的,我试过了,我甚至没有想到使用一个set。但是我仍然得到了重复项 :( 。所以我的代码正在读取一个带有JSON列的CSV文件。我正在使用GSON将JSON解析为public Set<List<float[]>> coordinates = new HashSet<>();。当我使用List<float[]> tmp = p.coordinates.iterator().next();输出它们时, for(int i=0; i<tmp.size(); i++){ System.out.println(Arrays.toString(tmp.get(i))); }仍然有重复项。 - user2524908
2
问题在于数组的equals方法与arr1 == arr2相同。然而,您有两个具有相同值的不同引用。我的猜测是:扩展ArrayList并覆盖equals方法(您还需要重写hashcode方法,因为您将使用HashSet),以使用Arrays.equals(arr1,arr2)。因此,您将拥有Set<List<float []>> set = new HashSet<MyArrayList<float []>>(); 聪明的IDE将为您生成哈希码。 - Silviu Burcea
很抱歉,我对Java的经验不是很丰富。MyArrayList是指什么?是我的变量List<List<float[]>> tmp;吗? - user2524908
-1 表示扩展 ArrayList,这基本上总是一个不好的想法,相反你几乎肯定应该创建一个自定义类来包装一个 float[] - Louis Wasserman
显示剩余2条评论

1
怎么样:
List<List<Float[]>> outterList;
Set<Float[]> mySet = new HashSet<Float[]>();
for (List<Float[]> innerList : outterList){
    Iterator<Float[]> iterator = innerList.iterator();
    while(iterator.hasNext()){
        Float[] array = iterator.next();
        boolean added = mySet.add(array);
        if (!added)
           iterator.remove();
    }
}

为了进行比较,请尝试通过 new BigDecimal(double, MathContext) 转换为 BigDecimal 更新: 测试失败。似乎在 HashSet 中比较数组存在问题。
@Test
public void testArrays() {
    Set<String[]> set = new HashSet<String[]>();
    set.add(new String[] { "12.3f", "33.4f" });
    Assert.assertFalse(set.add(new String[] { "12.3f", "33.4f" }));
}

更新

所以数组的工作方式不同。以下是详细说明:

这里使用了Guava的PredicateIterables.any()。与使用Set相比,此解决方案效率较低,因为它每次都必须迭代List,但如果性能不是问题,则可以使用它。

private static <T> Predicate<T[]> equals(final T[] array) {
    return new Predicate<T[]>() {

        @Override
        public boolean apply(T[] arg0) {
            return Arrays.equals(array, arg0);
        }
    };
}

public static <T> List<List<T[]>> ProcessList(List<List<T[]>> old) {
    List<T[]> mySet = new ArrayList<T[]>();
    for (List<T[]> innerList : old) {
        Iterator<T[]> iterator = innerList.iterator();
        while (iterator.hasNext()) {
            T[] array = iterator.next();
            Predicate<T[]> contains = equals(array);

            if (Iterables.any(mySet, contains)) {
                iterator.remove();
            } else {
                mySet.add(array);
            }
        }
    }
    // for (int i = 0; i < old.get(0).size(); i++) {
    // System.out.println(java.util.Arrays.toString(old.get(0).get(i)));
    // }
    return old;
}

这个测试:

@Test
public void testListsFloat() {
    List<List<Float[]>> outter = new ArrayList();

    List<Float[]> inner1 = new ArrayList();
    inner1.add(new Float[] { 12.3f, 33.4f });
    inner1.add(new Float[] { 12.2f, 33.2f });
    inner1.add(new Float[] { 12.3f, 33.4f });

    List<Float[]> inner2 = new ArrayList();
    inner2.add(new Float[] { 12.1f, 33.1f });
    inner2.add(new Float[] { 12.2f, 33.2f });
    inner2.add(new Float[] { 12.3f, 33.4f });

    outter.add(inner1);
    outter.add(inner2);

    outter = ProcessList(outter);
    for (List<Float[]> list : outter) {
        for (Float[] array : list) {
            System.out.println(Arrays.toString(array));
        }
    }
}

这导致了以下输出结果:

[12.3, 33.4] [12.2, 33.2] [12.1, 33.1]


1
返回 outterList。现在已通过迭代器的“remove”调用进行了修改。 - John B
哦,看起来还是包含重复项。public static List<List<float[]>> ProcessList(List<List<float[]>> old){ Set<float[]> mySet = new HashSet<float[]>(); for (List<float[]> innerList : old){ Iterator<float[]> iterator = innerList.iterator(); while(iterator.hasNext()){ float[] array = iterator.next(); boolean added = mySet.add(array); if (!added) iterator.remove(); } }for(int i=0; i} - user2524908
1
请提供表明它没有起作用的输出?您对重复项的定义是什么?这只会删除重复的数组(两个具有完全相同元素且顺序相同的数组)。 - John B
哦,你可能也遇到了比较浮点数值的问题。浮点数不是精确的,所以这可能是问题的一部分。请澄清一下。 - John B
抱歉,我的工作中聊天被阻止了。不过,我已经发布了应该有效的解决方案。 - John B
显示剩余7条评论

0

在填充时,您可以使用LinkedHashSet来避免重复。虽然它是Set的实现,但如果需要List方法,您可以将其包装成List


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接