Java:检测ArrayList中的重复项?
我怎么能检测(返回true / false)一个ArrayList是否包含多个Java中相同的元素?
非常感谢,特里
编辑忘了提及,我不是要比较“块”彼此,但它们的整数值。 每个“块”有一个int,这是什么使他们不同。 我通过调用名为“getNum”的方法(例如table1 [0] [2] .getNum();
最简单:将整个集合转储到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实现了“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]);
…
改进的代码,使用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; }
如果你正在寻找避免重复,那么你应该删除检测重复的中间过程,并使用Set 。
如果你的元素在某种程度上是可比较的(事实上,这个顺序有任何真正的含义是无关紧要的 – 它只需要和你定义的相等一致),最快的重复删除解决scheme将sorting列表(0(n log n)))然后做一个单一的过程,并寻找重复的元素(即,相等的元素相互跟随)(这是O(n))。
整体的复杂度将会是O(n log(n)),这与使用Set(n倍long(n))得到的结果大致相同,但是常数要小得多。 这是因为sort / dedup中的常量是比较元素的成本的结果,而来自集合的成本很可能是由散列计算产生的,另外还有一个(可能是几个)散列比较。 如果你使用的是一个基于散列的Set实现,也就是说,因为一个Tree会给你一个O(n log2(n)),这更糟糕。
但据我了解,您不需要删除重复项目,只需testing它们的存在。 所以你应该在你的数组上手工编写一个合并或堆sortingalgorithm,如果你的比较器返回0就退出返回true(即“有一个dup”),否则完成sorting,并遍历有序数组testing重复。 在合并或堆sorting中,实际上,当sorting完成后,除非两个元素已经在最终位置(这不太可能),否则您将比较每个重复对。 因此,一个调整sortingalgorithm应该产生巨大的性能改进(我将不得不certificate,但我想调整后的algorithm应该是在统一随机数据上的O(log(n)))
改进的代码来返回重复的元素
- 可以在集合中find重复项
- 返回重复的集合
- 独特元素可以从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; }
我需要为Stream
做类似的操作,但找不到一个好的例子。 这是我想出来的。
public static <T> boolean areUnique(final Stream<T> stream) { final Set<T> seen = new HashSet<>(); return stream.allMatch(seen::add); }
这有一个好处,就是在发现重复数据的时候,不必处理整个数据stream,而只是把所有数据都放在一个数据Set
然后检查数据的大小。 所以这种情况大概是:
List<T> list = ... boolean allDistinct = areUnique(list.stream());
简单地说:1)确保所有项目是可比较的2)对数组进行sorting2)遍历数组并重复查找
要知道列表中的重复使用以下代码:它会给你包含重复的集合。
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; }
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 }
注意:虽然从列表开始删除了项目,但是这会产生重大的性能影响。 为了解决这个问题,我们有两个select。 1)以相反的顺序迭代并删除元素。 2)使用LinkedList而不是ArrayList。 由于在访谈中询问有偏见的问题,从列表中删除重复,而不使用任何其他收集,上面的例子是答案。 但是在现实世界中,如果我必须实现这一点,我将把List中的元素设置为简单!
/** * 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; } }
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); } }
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);
处理这个问题的最好方法是使用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,看到结果没有重复:)