我如何去检测(返回true / false)ArrayList是否包含Java中多个相同元素?
非常感谢,特里
编辑 忘记提及我不是要相互比较“块”,而是要比较它们的整数值。每个“块”都有一个整数,这就是它们与众不同的原因。我通过调用名为“ getNum”的方法(例如,table1 [0] [2] .getNum();)来找到特定Block的int。
我如何去检测(返回true / false)ArrayList是否包含Java中多个相同元素?
非常感谢,特里
编辑 忘记提及我不是要相互比较“块”,而是要比较它们的整数值。每个“块”都有一个整数,这就是它们与众不同的原因。我通过调用名为“ getNum”的方法(例如,table1 [0] [2] .getNum();)来找到特定Block的int。
Answers:
最简单:将整个集合转储到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数组,如下所示
块表[] [];
并且您想检测其中是否有重复的行?
在那种情况下,假设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
如果要添加的项已经在集合中,则返回boolean false,因此false
如果您想知道是否存在重复项,您甚至可以短路并打包返回的任何添加项。
改进的代码,使用返回值of Set#add
而不是比较list和set的大小。
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());
?给定一个List参数,我认为如果列表不包含重复项是很有效的。
HashSet
,由于哈希结构的基础加载因素,甚至将s的大小调整为列表大小也将导致在遍历整个列表时调整大小。
改进的代码可返回重复元素
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;
}
如果您的元素在某种程度上是可比的(该顺序具有任何实际含义的事实并不重要-它只需要与您对相等性的定义保持一致),则最快的重复删除解决方案将对列表进行排序(0(n log( n)))然后进行单遍查找重复元素(即彼此跟随的相等元素)(这是O(n))。
整体复杂度将为O(n log(n)),与使用Set(n倍long(n))所得到的结果大致相同,但常数要小得多。这是因为排序/重复的常量是由比较元素的成本引起的,而集合中的成本最有可能是由哈希计算以及一个(可能是多个)哈希比较得出的。如果您使用的是基于散列的Set实现,那是因为基于Tree的树将为您提供O(nlog²(n)),甚至更糟。
但是据我了解,您不需要删除重复项,而只需测试它们的存在。因此,您应该在阵列上手动编码合并或堆排序算法,如果比较器返回0,则退出返回true(即“ dup”),否则就完成排序,并遍历排序的数组测试是否重复。实际上,在合并或堆排序中,当排序完成时,您将比较每个重复对,除非两个元素都已经处于其最终位置(这不太可能)。因此,经过调整的排序算法应该会产生巨大的性能改进(我必须证明这一点,但是我想经过调整的算法应该在均匀随机数据的O(log(n))中)
我需要对进行类似的操作Stream
,但找不到一个很好的例子。这是我想出的。
public static <T> boolean areUnique(final Stream<T> stream) {
final Set<T> seen = new HashSet<>();
return stream.allMatch(seen::add);
}
这样做的优点是,尽早发现重复项时会发生短路,而不是必须处理整个流,并且这样做并不比将所有内容都放入a Set
并检查大小而复杂得多。因此,这种情况大致为:
List<T> list = ...
boolean allDistinct = areUnique(list.stream());
使用Java 8+,您可以使用Stream API:
boolean areAllDistinct(List<Block> blocksList) {
return blocksList.stream().map(Block::getNum).distinct().count() == blockList.size();
}
要了解列表中的重复项,请使用以下代码:它将为您提供包含重复项的集合。
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);
只需打印 结果 arraylist并查看没有重复的结果即可:)
如果要使用重复值集:
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);
}
}
可能还会考虑修剪值或使用小写字母...视您的情况而定。
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中删除重复项,因此上述示例就是答案。但是,在现实世界中,如果必须实现这一点,我将把List到Set中的元素简单化!
/**
* 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;
}
}
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);
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;
}