如何在Java中检测(返回true/false)一个ArrayList是否包含多个相同的元素?
非常感谢, Terry
编辑 忘记提到我不想将“块”与彼此进行比较,而是比较它们的整数值。 每个“块”都有一个int,这就是它们的不同之处。 通过调用名为“getNum”的方法(例如table1 [0] [2] .getNum();)可以找到特定块的int。
如何在Java中检测(返回true/false)一个ArrayList是否包含多个相同的元素?
非常感谢, Terry
编辑 忘记提到我不想将“块”与彼此进行比较,而是比较它们的整数值。 每个“块”都有一个int,这就是它们的不同之处。 通过调用名为“getNum”的方法(例如table1 [0] [2] .getNum();)可以找到特定块的int。
最简单的方法是将整个集合转储到一个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 */
}
更新:如果我正确理解你的问题,你有一个Block的2D数组,就像for (Block[] row : table) {
Set set = new HashSet<Block>();
for (Block cell : row) {
set.add(cell);
}
if (set.size() < 6) { //has duplicate
}
}
对于语法,我并不能百分之百确定,所以最好写成以下形式更为安全
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
如果添加的元素已经存在于集合中,返回一个布尔值 false。因此,如果你只想知道是否有重复项,甚至可以在返回 false
的任何添加操作上进行短路并退出。
优化代码,使用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<T> set = new HashSet<T>(list.size());
会更加高效。 - Paul JacksonHashSet
的大小调整为列表的大小,由于哈希结构的基础负载因子,在运行整个列表时也会导致重新调整大小。 - Jay Anderson使用Java 8+可以使用Stream API:
boolean areAllDistinct(List<Block> blocksList) {
return blocksList.stream().map(Block::getNum).distinct().count() == blockList.size();
}
如果您希望完全避免重复项,那么您应该削减掉检测重复的中间过程,而使用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);
}
这种方法的优点是,当发现重复项时可以直接短路而不必处理整个流,而且比仅将所有内容放入Set
并检查大小要简单得多。因此,该情况大致如下:
List<T> list = ...
boolean allDistinct = areUnique(list.stream());
return stream.allMatch(new HashSet<>()::add);
,意思是检查stream中的所有元素是否都可以被添加到一个新的HashSet中。 - Jezor如果您想要重复值的集合:
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);
}
}
根据您的情况,可能需要考虑修剪值或使用小写字母。
要查找列表中的重复项,请使用以下代码:它将返回包含重复项的集合。
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;
}
处理这个问题的最佳方法是使用一个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);