-2

我正在使用 Set 来隔离 List 的唯一值(在这种情况下,我得到了一组点):

Set<PVector> pointSet = new LinkedHashSet<PVector>(listToCull);

这将返回一组唯一点,但对于listToCull中的每个项目,我想测试以下内容:如果有重复项,则剔除所有重复项。换句话说,我希望 pointSet 表示 listToCull 中已经唯一的项目集(pointSet中的每个项目在listToCull中没有重复)。关于如何实施的任何想法?

编辑 - 我认为我的第一个问题需要更多澄清。下面是一些将执行我要求的代码,但我想知道是否有更快的方法。假设 listToCull 是具有重复项的 PVector 列表:

Set<PVector> pointSet = new LinkedHashSet<PVector>(listToCull);
    List<PVector> uniqueItemsInListToCull = new ArrayList<PVector>();
    for(PVector pt : pointSet){
        int counter=0;
        for(PVector ptCheck : listToCull){
            if(pt==ptCheck){
                counter++;
            }
        }
        if(counter<2){
            uniqueItemsInListToCull.add(pt);
        }
    }

uniqueItemsInListToCull 将不同于 pointSet。如果可能的话,我想在没有循环的情况下做到这一点。

4

4 回答 4

2

您必须自己进行一些编程:创建两个空集;on 将包含唯一元素,其他元素将包含重复项。然后循环遍历listToCull. 对于每个元素,检查它是否在重复集中。如果是,请忽略它。否则,检查它是否在唯一元素集中。如果是,请将其删除并添加到重复集。否则,将其添加到唯一元素集中。

如果你的PVector类有一个好的hashCode()方法,HashSets 的效率是相当高的,所以 this 的性能不会太差。

未经测试:

Set<PVector> uniques = new HashSet<>();
Set<PVector> duplicates = new HashSet<>();
for (PVector p : listToCull) {
    if (!duplicates.contains(p)) {
        if (uniques.contains(p)) {
            uniques.remove(p);
            duplicates.add(p);
        }
        else {
            uniques.add(p);
        }
    }
}

或者,您可以使用提供BagMultiSet. 这允许您计算每个元素在集合中出现的次数,然后在最后丢弃计数不等于 1 的所有元素。

于 2015-08-28T21:39:38.880 回答
0

因此,您希望 pointSet 保存 listToCull 中没有重复项的项目?那正确吗?

我倾向于创建一个 Map,然后在列表上迭代两次,第一次为每个 PVector 输入一个零值,第二次为每个 PVector 的值加一个,所以最后你有一个地图计数。现在您对值完全等于 1 的映射键感兴趣。

它的效率并不高——你对列表项的操作次数超过了绝对必要的次数——但它非常干净和简单。

于 2015-08-28T23:01:12.050 回答
0

您正在寻找的是intersection

假设PVector顺便说一句可怕的名字)实现hashCode()equals()正确地 aSet将消除重复。

如果你想要一个intersectionof theList和一个现有的Setcreate a Setfrom the Listthen 使用Sets.intersection()from Guava来获得两个集合共有的那些。

public static <E> Sets.SetView<E> intersection(Set<E> set1, Set<?> set2) 

返回两个集合交集的不可修改视图。返回的集合包含两个支持集合所包含的所有元素。返回集合的迭代顺序与 set1 的迭代顺序一致。如果 set1 和 set2 是基于不同等价关系的集合(如 HashSet、TreeSet 和 IdentityHashMap 的 keySet 都是),则结果未定义。

注意:当 set1 是两个集合中较小的一个时,返回的视图性能稍好。如果您有理由相信您的一组通常会比另一组小,请先通过它。不幸的是,由于此方法根据传递的第一个集合的类型设置返回集合的泛型类型,因此在极少数情况下,这可能会迫使您进行强制转换,例如:

设置 aFewBadObjects = ... 设置 manyBadStrings = ...

// 非字符串不可能在交集
SuppressWarnings("unchecked") Set badStrings = (Set) Sets.intersection( aFewBadObjects, manyBadStrings); 这是不幸的,但应该很少出现。

你也可以很容易地做union, complement, differenceand cartesianProductas well 。filter

于 2015-08-28T21:35:52.013 回答
0

好的,这是我想出的解决方案,我敢肯定那里有更好的解决方案,但这个对我有用。感谢所有给予指导的人!

要获取唯一项目,您可以运行 Set,其中 listToCull 是具有重复项的Pvector列表:

    List<PVector> culledList = new ArrayList<PVector>();
    Set<PVector> pointSet = new LinkedHashSet<PVector>(listToCull);
    culledList.addAll(pointSet);

更进一步,假设您想要一个列表,其中删除了 listToCull 中所有具有重复项的项目。您可以遍历列表并测试它是否在每个项目的集合中。这让我们做一个循环,而不是一个嵌套循环:

    Set<PVector> pointSet = new HashSet<PVector>(listToCull);
    Set<PVector> removalList = new HashSet<PVector>();//list to remove

    for (PVector pt : listToCull) {
        if (pointSet.contains(pt)) {
            removalList.add(pt);
        }
        else{
            pointSet.add(pt);
        }
    }
    pointSet.removeAll(removalList);
    List<PVector> onlyUniquePts = new ArrayList<PVector>();
    onlyUniquePts.addAll(pointSet);
于 2015-08-31T21:51:00.007 回答