我正在使用一个集合从ArrayList(从数据库填充)中获取重复项的列表
void getDuplicateHashTest() {
List<BroadcastItem> allDataStoreItems = itemsDAO.getAllItems();
Set<BroadcastItem> setOfAllData = new HashSet<>(allDataStoreItems);
List<BroadcastItem> diff = new ArrayList<>(setOfAllData);
allDataStoreItems.removeAll(diff);
}
所以在最后一行,所有不重复的项目都应该从所有项目的列表中删除。
问题是当我打印allDataStoreItems.size()
时我得到0
设置和子列表打印正确的项目数。
我做错了什么?
答案 0 :(得分:2)
List#removeAll
删除所有出现的给定元素,而不仅仅是其中一个(与List#remove
相反,后者仅删除第一次出现)。因此setOfAllData
包含列表中每个元素的一个副本,然后删除每个元素的所有匹配项,这意味着您总是会以空列表结束。
要知道如何解决这个问题,我需要了解更多关于你想要的结果。你想要删除每个元素的一个副本吗?如果是这样,你可以用:
List<BroadcastItem> allDataStoreItems = itemsDAO.getAllItems();
Set<BroadcastItem> setOfAllData = new HashSet<>(allDataStoreItems);
setOfAllData.forEach(allDataStoreItems::remove);
答案 1 :(得分:2)
如果你只想存储重复项就很简单,找到下面的代码。
Set<BroadcastItem> duplicates = new HashSet<>;
Set<BroadcastItem> allItems=new HashSet<>
for(BroadcastItem b:allDataStoreItems){
boolean x=allItems.add(b);
if(x==false){
duplicates.add(b);
}
}
答案 2 :(得分:1)
正如answer by jacobm中已经指出的那样:Collection#removeAll
方法将删除所有特定元素的出现。但是,创建列表并重复调用remove
的替代方案并不是一个很好的解决方案:在List
上,remove
调用通常会有O(n)复杂度,因此找出像这样的重复将具有二次复杂性。
更好的解决方案是shamsher Khan in his answer (+1!)已经提到的解决方案:您可以使用Set
遍历列表,并跟踪已经看到的元素。
该解决方案具有O(n)的复杂性。
目前尚不清楚是否需要所有重复项的列表或集。例如,当输入为[1, 2,2,2, 3]
时,结果应为[2,2]
还是[2]
?但是,您可以简单地计算重复项的列表,并在必要时在第二步中使其元素唯一。
以下是一个例子:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
public class FindDuplicatesInList
{
public static void main(String[] args)
{
List<Integer> list = Arrays.asList(0,1,1,1,2,3,3,4,5,6,7,7,7,8);
List<Integer> duplicates = computeDuplicates(list);
// Prints [1, 1, 3, 7, 7]
System.out.println(duplicates);
// Prints [1, 3, 7]
System.out.println(makeUnique(duplicates));
}
private static <T> List<T> makeUnique(List<? extends T> list)
{
return new ArrayList<T>(new LinkedHashSet<T>(list));
}
private static <T> List<T> computeDuplicates(List<? extends T> list)
{
Set<T> set = new HashSet<T>();
List<T> duplicates = new ArrayList<T>();
for (T element : list)
{
boolean wasNew = set.add(element);
if (!wasNew)
{
duplicates.add(element);
}
}
return duplicates;
}
}