剔除集合中的所有重复项

时间:2015-08-28 21:26:00

标签: java set set-theory

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

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

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

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

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 个答案:

答案 0 :(得分:2)

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

如果您的PVector班级使用了hashCode()方法,HashSet非常有效,那么这样做的效果也不会太差。

未测试:

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的所有元素。

答案 1 :(得分:0)

您要找的是intersection

假设PVector可怕的名称)正确实施hashCode()equals()Set将消除重复。

如果您希望intersection List而现有SetSet创建List,请使用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 =   ...

     

//非String不可能在交叉点中   抑制警告(&#34;未选中&#34;)设置badStrings =(设置)   Sets.intersection(          aFewBadObjects,manyBadStrings);这是不幸的,但应该很少出现。

您也可以非常轻松地执行unioncomplementdifferencecartesianProduct以及filter

答案 2 :(得分:0)

所以你想让pointSet保存listToCull中没有重复项的项目吗?是吗?

我倾向于创建一个Map,然后在列表上迭代两次,第一次为每个PVector设置一个零值,第二次为每个PVector添加一个值,所以最后你有有计数的地图。现在,您对地图的键感兴趣,其值恰好等于一。

效率不高 - 您在列表项目上的操作次数超过了绝对必要的次数 - 但它非常简洁明了。

答案 3 :(得分:0)

好的,这是我提出的解决方案,我确定那里有更好的解决方案,但这个人正在为我工​​作。感谢所有给予指导的人!

要获取唯一项目,您可以运行一个Set,其中listToCull是一个包含重复项的PVectors列表:

    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);