[英]Removing duplicates from arraylist
for (int i=0; i<name.size(); i++)
{
for (int j = 1; j<name.size(); j++)
if (name.get(i).equals(name.get(j)))
{
name.remove(i);
name.remove(j);
j=j-1;
}
}
最初, name
是一个包含400个元素的ArrayList
。 我正在尝试删除重复的元素。 我不知道为什么我的编译器不断给我
java.lang.IndexOutOfBoundsException:索引:1,大小:1
请注意,我正在尝试删除重复的对。 arraylist中只能有两个相同的元素。 不能超过3。
我认为这可行。 您有2个小错误。
for (int i = 0; i < name.size(); i++)
{
for (int j = i + 1; j < name.size(); j++) // j needs to start at i + 1 not 1.
if (name.get(i).equals(name.get(j)))
{
name.remove(j); // You need to remove at the higher index
name.remove(i); // first, because items are shifted left.
j = j - 1;
}
}
从列表中删除项目时,索引会发生变化,这不仅会导致IndexOutOfBounds
,而且可能意味着您删除了错误的值
现在,将有多种方法可以实现此目标,例如...
List<String> name = new ArrayList<>(Arrays.asList(new String[]{"a", "b", "a"}));
List<String> discard = new ArrayList<>(25);
for (int outter = 0; outter < name.size(); outter++) {
String match = name.get(outter);
discard.clear();
for (int inner = outter + 1; inner < name.size(); inner++) {
String to = name.get(inner);
if (match.equals(to)) {
discard.add(to);
}
}
if (discard.size() > 0) {
discard.add(match);
name.removeAll(discard);
}
}
System.out.println(name);
打印...
[b]
这只是在内部循环中收集所有匹配的元素,然后将它们放入另一个List
,然后在内部循环完成之后将其传递到原始List
的removeAll
方法
内部循环从当前/外部索引(加1)开始,因为我们已经处理了它之前的所有值,所以我们不需要继续循环这些项
从理论上讲,您可以简单地继续向discard
List
添加元素,并在末尾执行单个removeAll
更新...
因此,我想知道是否可能存在使用Java 8以及Stream
支持的另一种解决问题的方法...
List<String> name = new ArrayList<>(Arrays.asList(new String[]{"a", "b", "a"}));
Set<String> allItems = new HashSet<>();
List<String> duplicates = name.stream()
.filter(n -> !allItems.add(n)) //Set.add() returns false if the item was already in the set.
.collect(Collectors.toList());
name.removeAll(duplicates);
因此,基本上,这样做是将name
List
中的所有重复项收集起来,并将它们放入duplicates
List
(使用allItems
作为临时保存点)。
然后,您可以简单地使用它调用removeAll
来删除所有重复项。
现在,这依赖于hashcode
并且equals
实现的对象的实现
我不会从您要遍历的列表中删除项目。 可以调整索引,但这会使难以阅读的代码成为可能。
相反,您可以使用Iterator
,它将为您处理索引调整。
这是一个简单的示例来说明这个概念(我在某种程度上简化了您的问题,在这种情况下,我不检查重复项,只是“ bob”):
ArrayList<String> names = getNames(); // populate the list with some names
Iterator<String> iterator = names.iterator();
while(iterator.hasNext()) {
String name = iterator.next();
if(name.equals("bob")) {
iterator.remove();
}
}
但是,要查找重复项,我将完全使用另一种方法。 与其使用嵌套循环,不如使用Set
集合。 集合不能包含重复项,并且如果您尝试将重复项添加到集合中,则add()
方法将返回false。
如果您遍历列表,请将每个项目添加到集合中,并检查add()
方法是否返回false,您将知道何时有重复项。 您可以将其从列表中删除,也可以将其保留在末尾,然后将其用于没有重复的名称集合。
这里有一个问题,带有一个说明此方法的答案。 您将以这种方式消耗更多的空间(在内存中将有一个列表和一个集合),但是由于每次需要检查重复项时都不需要遍历列表,因此可以节省大量时间。 根据您列表的大小,这可能不理想。
编辑:实际上,您可以只选择名称列表,然后将其批量添加到集合中,重复项将被删除:
Set<String> namesNoDuplicates = new HashSet<String>();
namesNoDuplicates.addAll(names);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.