Java:检测ArrayList中的重复项?

时间:2009-02-18 21:22:31

标签: java arrays arraylist duplicates

我怎样才能检测(返回true / false)ArrayList中是否包含多个相同的元素?

非常感谢, 特里

修改 忘了提一下我不打算将“块”相互比较,而是将它们的整数值进行比较。每个“块”都有一个int,这就是它们的不同之处。 我通过调用名为“getNum”的方法找到特定块的int(例如table1 [0] [2] .getNum();

16 个答案:

答案 0 :(得分:165)

最简单:将整个集合转储到Set中(使用Set(Collection)构造函数或Set.addAll),然后查看Set是否与ArrayList具有相同的大小。

List<Integer> list = ...;
Set<Integer> set = new HashSet<Integer>(list);

if(set.size() < list.size()){
    /* There are duplicates */
}

更新:如果我正确理解你的问题,你有一个2d的Block数组,如

阻止表[] [];

并且您想检测它们中的任何一行是否有重复项?

在这种情况下,假设Block正确实现“equals”和“hashCode”,我可以执行以下操作:

for (Block[] row : table) {
   Set set = new HashSet<Block>(); 
   for (Block cell : row) {
      set.add(cell);
   }
   if (set.size() < 6) { //has duplicate
   }
}

我对语法不是100%肯定,因此将其写为

可能更安全
for (int i = 0; i < 6; i++) {
   Set set = new HashSet<Block>(); 
   for (int j = 0; j < 6; j++)
    set.add(table[i][j]);

...

答案 1 :(得分:57)

改进了代码,使用Set#add的返回值,而不是比较列表和集合的大小。

public static <T> boolean hasDuplicate(Iterable<T> all) {
    Set<T> set = new HashSet<T>();
    // Set#add returns false if the set does not change, which
    // indicates that a duplicate element has been added.
    for (T each: all) if (!set.add(each)) return true;
    return false;
}

答案 2 :(得分:15)

如果您希望完全避免重复,那么您应该删除检测重复项的中间过程并使用Set

答案 3 :(得分:10)

改进了返回重复元素的代码

  • 可以在集合中找到重复项
  • 返回重复项集
  • 可以从Set
  • 获取唯一元素

public static <T> List getDuplicate(Collection<T> list) {

    final List<T> duplicatedObjects = new ArrayList<T>();
    Set<T> set = new HashSet<T>() {
    @Override
    public boolean add(T e) {
        if (contains(e)) {
            duplicatedObjects.add(e);
        }
        return super.add(e);
    }
    };
   for (T t : list) {
        set.add(t);
    }
    return duplicatedObjects;
}


public static <T> boolean hasDuplicate(Collection<T> list) {
    if (getDuplicate(list).isEmpty())
        return false;
    return true;
}

答案 4 :(得分:9)

如果你的元素在某种程度上是可比较的(订单有任何实际意义的事实是无关紧要的 - 它只需要与你的相等定义一致),最快的重复删除解决方案将对列表进行排序(0( n log(n)))然后进行单次传递并查找重复的元素(即相互跟随的相等元素)(这是O(n))。

整体复杂度将是O(n log(n)),这与使用Set(n倍长(n))得到的大致相同,但具有更小的常量。这是因为sort / dedup中的常量来自比较元素的成本,而来自集合的成本最有可能来自散列计算,加上一个(可能是几个)散列比较。如果你使用的是基于散列的Set实现,也就是说,因为基于树的将给你一个O(nlog²(n)),这更糟糕。

但据我所知,您不需要删除重复项,而只是测试它们的存在。所以你应该在你的数组上手动编写一个合并或堆排序算法,如果你的比较器返回0,它只是退出返回true(即“有一个dup”),否则完成排序,并遍历排序的数组测试重复。实际上,在合并或堆排序中,当排序完成时,您将比较每个重复对,除非这两个元素已经位于其最终位置(这是不可能的)。因此,调整排序算法应该会产生巨大的性能提升(我必须证明这一点,但我想调整后的算法应该在O(log(n))上的统一随机数据上)

答案 5 :(得分:8)

我需要为Stream执行类似的操作,但找不到好的示例。这就是我想出来的。

public static <T> boolean areUnique(final Stream<T> stream) {
    final Set<T> seen = new HashSet<>();
    return stream.allMatch(seen::add);
}

这有利于在早期发现重复项时发生短路,而不是必须处理整个流,并且比将所有内容放入Set并检查大小要复杂得多。所以这个案子大致是:

List<T> list = ...
boolean allDistinct = areUnique(list.stream());

答案 6 :(得分:2)

简单地说: 1)确保所有项目都具有可比性 2)对数组进行排序 2)迭代数组并找到重复项

答案 7 :(得分:1)

要知道列表中的重复项,请使用以下代码:它将为您提供包含重复项的集合。

 public Set<?> findDuplicatesInList(List<?> beanList) {
    System.out.println("findDuplicatesInList::"+beanList);
    Set<Object> duplicateRowSet=null;
    duplicateRowSet=new LinkedHashSet<Object>();
            for(int i=0;i<beanList.size();i++){
                Object superString=beanList.get(i);
                System.out.println("findDuplicatesInList::superString::"+superString);
                for(int j=0;j<beanList.size();j++){
                    if(i!=j){
                         Object subString=beanList.get(j);
                         System.out.println("findDuplicatesInList::subString::"+subString);
                         if(superString.equals(subString)){
                             duplicateRowSet.add(beanList.get(j));
                         }
                    }
                }
            }
            System.out.println("findDuplicatesInList::duplicationSet::"+duplicateRowSet);
        return duplicateRowSet;
  }

答案 8 :(得分:1)

如果您想要一组重复值:

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class FindDuplicateInArrayList {

    public static void main(String[] args) {

        Set<String> uniqueSet = new HashSet<String>();
        List<String> dupesList = new ArrayList<String>();
        for (String a : args) {
            if (uniqueSet.contains(a))
                dupesList.add(a);
            else
                uniqueSet.add(a);
        }
        System.out.println(uniqueSet.size() + " distinct words: " + uniqueSet);
        System.out.println(dupesList.size() + " dupesList words: " + dupesList);
    }
}

并且可能还考虑修剪值或使用小写......取决于你的情况。

答案 9 :(得分:1)

处理此问题的最佳方法是使用 HashSet

ArrayList<String> listGroupCode = new ArrayList<>();
listGroupCode.add("A");
listGroupCode.add("A");
listGroupCode.add("B");
listGroupCode.add("C");
HashSet<String> set = new HashSet<>(listGroupCode);
ArrayList<String> result = new ArrayList<>(set);

只需打印结果 arraylist并查看结果,无需重复:)

答案 10 :(得分:1)

使用Java 8+,您可以使用Stream API:

boolean areAllDistinct(List<Block> blocksList) {
    return blocksList.stream().map(Block::getNum).distinct().count() == blockList.size();
}

答案 11 :(得分:0)

    String tempVal = null;
    for (int i = 0; i < l.size(); i++) {
        tempVal = l.get(i); //take the ith object out of list
        while (l.contains(tempVal)) {
            l.remove(tempVal); //remove all matching entries
        }
        l.add(tempVal); //at last add one entry
    }

注意:虽然从列表的开头删除了项目,但这会有很大的性能提升。 为解决这个问题,我们有两种选择。 1)以相反的顺序迭代并删除元素。 2)使用LinkedList而不是ArrayList。由于在访谈中提出的有偏见的问题在不使用任何其他集合的情况下从列表中删除重复,上面的例子就是答案。但在现实世界中,如果我必须实现这一点,我会将List中的元素放到Set中,简单!

答案 12 :(得分:0)

/**
     * Method to detect presence of duplicates in a generic list. 
     * Depends on the equals method of the concrete type. make sure to override it as required.
     */
    public static <T> boolean hasDuplicates(List<T> list){
        int count = list.size();
        T t1,t2;

        for(int i=0;i<count;i++){
            t1 = list.get(i);
            for(int j=i+1;j<count;j++){
                t2 = list.get(j);
                if(t2.equals(t1)){
                    return true;
                }
            }
        }
        return false;
    }

已覆盖equals()的具体类的示例:

public class Reminder{
    private long id;
    private int hour;
    private int minute;

    public Reminder(long id, int hour, int minute){
        this.id = id;
        this.hour = hour;
        this.minute = minute;
    }

    @Override
    public boolean equals(Object other){
        if(other == null) return false;
        if(this.getClass() != other.getClass()) return false;
        Reminder otherReminder = (Reminder) other;
        if(this.hour != otherReminder.hour) return false;
        if(this.minute != otherReminder.minute) return false;

        return true;
    }
}

答案 13 :(得分:0)

    ArrayList<String> withDuplicates = new ArrayList<>();
    withDuplicates.add("1");
    withDuplicates.add("2");
    withDuplicates.add("1");
    withDuplicates.add("3");
    HashSet<String> set = new HashSet<>(withDuplicates);
    ArrayList<String> withoutDupicates = new ArrayList<>(set);

    ArrayList<String> duplicates = new ArrayList<String>();

    Iterator<String> dupIter = withDuplicates.iterator();
    while(dupIter.hasNext())
    {
    String dupWord = dupIter.next();
    if(withDuplicates.contains(dupWord))
    {
        duplicates.add(dupWord);
    }else{
        withoutDupicates.add(dupWord);
    }
    }
  System.out.println(duplicates);
  System.out.println(withoutDupicates);

答案 14 :(得分:0)

这个答案在Kotlin中写得很清楚,但是可以很容易地翻译成Java。

如果您的arraylist大小在固定的小范围内,那么这是一个很好的解决方案。

var duplicateDetected = false
    if(arrList.size > 1){
        for(i in 0 until arrList.size){
            for(j in 0 until arrList.size){
                if(i != j && arrList.get(i) == arrList.get(j)){
                    duplicateDetected = true
                }
            }
        }
    }

答案 15 :(得分:0)

private boolean isDuplicate() {
    for (int i = 0; i < arrayList.size(); i++) {
        for (int j = i + 1; j < arrayList.size(); j++) {
            if (arrayList.get(i).getName().trim().equalsIgnoreCase(arrayList.get(j).getName().trim())) {
                return true;
            }
        }
    }

    return false;
}