使用迭代器从 Java 中的列表中删除重复项
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15181395/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Removing duplicates from a List in Java using iterators
提问by user1542396
Im trying to work on an assignment question for my intro java course where we are supposed to remove duplicate items from a list without using sets or the .contains() method. Basically just using iterators and the .equals() method. My code is as follows:
我正在尝试为我的 Java 入门课程解决一个作业问题,我们应该在不使用集合或 .contains() 方法的情况下从列表中删除重复项。基本上只使用迭代器和 .equals() 方法。我的代码如下:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class sample {
public static void main(String[] args) throws BadListException {
List<String> myList = new ArrayList<String>();
myList.add("A");
myList.add("B");
myList.add("B");
myList.add("C");
myList.add("B");
myList.add("D");
unique(myList);
System.out.println(myList);
}
public static List<String> unique( List<String> items ) throws BadListException {
List<String> newList = new ArrayList<String>();
Iterator<String> itr = items.listIterator();
// If items is null, throw a BadListException.
if (items == null){
throw new BadListException();
}
// If items is empty, return a new empty list.
if (items.isEmpty()){
return newList;
}
// Otherwise create and return a new list that contains the items
// in L with all duplicates removed.
// Example: items: "A","B","C" result: "A","B","C"
// Example: items: "A","A","A" result: "A"
// Example: items: "A","B","B","C","A","D" result: "A","B","C","D"
while (itr.hasNext()){
for (int i = 0; i < items.size()-1; i++){
if (itr.next().equals(items.get(i))){
itr.remove();
}
}
}
items = newList;
return newList;
If someone could please explain what I'm doing wrong and how I should go about doing it instead that would be very helpful. Please note that since this is to prepare me for a test I would appreciate an explanation rather than just the correct piece of code.
如果有人可以解释我做错了什么以及我应该如何去做,那将非常有帮助。请注意,由于这是为我准备测试,因此我希望得到解释,而不仅仅是正确的代码段。
回答by Stephen C
Rather than explaining exactly what is going wrong, I'm going to suggest that you use a debugger to see what the program is currently doing. In particular, look at what the iterator is returning each time you call iter.next()
.
与其解释到底出了什么问题,不如建议您使用调试器来查看程序当前在做什么。尤其要注意每次调用时迭代器返回的内容iter.next()
。
Hints for a correct solution:
正确解决方案的提示:
- You will need to use more than one iterator ...
- You are not putting anything into the list you are returning.
- You need to make up you mind whether you are creating and returning a new list, or removing elements from the existing one. Doing BOTH doesn't make sense.
- 您将需要使用多个迭代器...
- 您没有将任何内容放入要返回的列表中。
- 您需要决定是创建并返回一个新列表,还是从现有列表中删除元素。两者都做没有意义。
In future, when you ask a question, you should provide a better statement of what the program is actually supposed to do. For instance:
将来,当您提出问题时,您应该更好地说明程序实际应该做什么。例如:
- You don't say whether the
unique
method is supposed to remove elements from the argument list or return a new list containing (just) the unique elements. - You don't say whether the order of the elements in the list(s) matters.
- You don't say whether it is OK to change the input list ... or not.
- 您没有说明该
unique
方法是否应该从参数列表中删除元素或返回一个包含(仅)唯一元素的新列表。 - 您没有说列表中元素的顺序是否重要。
- 你没有说是否可以更改输入列表......或不。
All of these things matter in deciding how to solve a problem like this. Especially in the real world. Even your assignment did not state these things, you still need to make up your own mind how your code is intended to work ... and document this with javadoc comments.
所有这些对于决定如何解决这样的问题都很重要。尤其是在现实世界中。即使你的作业没有说明这些事情,你仍然需要自己决定你的代码是如何工作的……并用 javadoc 注释记录下来。
回答by Kent
- when
i==0
youriterator.next()
andget(i)
would be the same element, so you just removed it. - for the same list, better not do
iterator.remove()
within afor
loop. - you didn't
add
anything to thenewList
, and returned it simply - a suggestion for this assignment:
- 当
i==0
您iterator.next()
和get(i)
将是相同的元素时,所以您只需将其删除。 - 对于同一个列表,最好不要
iterator.remove()
在for
循环中进行。 - 你
add
什么都没有newList
,只是简单地返回了它 - 对这个任务的建议:
you could first sortthe list, then go through it, if an element is equal to its previous one, remove the element. You could of course create a new list to hold those unique elements if you want.
您可以先对列表进行排序,然后遍历它,如果一个元素等于它的前一个元素,则删除该元素。如果需要,您当然可以创建一个新列表来保存这些独特的元素。
my 2 cents
我的 2 美分
回答by Floris
Iterating over a list and removing elements changes the list... If you looked at element "4" and decided to remove it, what is the next element you look at? Hint: it's not the original element "5" but the new element ”5”...
迭代列表并删除元素会更改列表...如果您查看元素“4”并决定删除它,那么您查看的下一个元素是什么?提示:不是原始元素“5”而是新元素“5”...
回答by Alan Smith
You could just create your own iterator whose purpose is to only return a duplicated value once.
您可以创建自己的迭代器,其目的是只返回重复值一次。
public class NoDuplicatesIterator<T> implements Iterator<T> {
private final List<T> array;
private final List<T> encountered;
private int index = 0;
public NoDuplicatesIterator(List<T> array) {
this.array = array;
encountered = new ArrayList<>();
}
@Override
public boolean hasNext() {
if (index > array.size() - 1) {
return false;
}
while (encountered.contains(array.get(index)) && index < array.size() - 1) {
index++;
}
return index <= array.size() - 1;
}
@Override
public T next() {
encountered.add(array.get(index));
return array.get(index++);
}
}
Usage:
用法:
public class Main {
public static void main(String[] args) {
List<Integer> array = Arrays.asList(new Integer[]{100, 2, 2, 1, 1, 2, 3, 3, 15, 4, 4, 5, 6, 7, 7, 8, 99, 99, 100, 99, 2, 77, 23, 14, 2, 15});
NoDuplicatesIterator<Integer> it = new NoDuplicatesIterator(array);
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
回答by Peter
Below is the solution :
以下是解决方案:
List<String> list = Lists.newArrayList("1","4","8","1","4","5","1");
Collections.sort(list);
Iterator<String> itr = list.iterator();
String old = itr.next();
while(itr.hasNext())
{
String next = itr.next();
if(old.equals(next))
{
itr.remove();
}
old = next;
}
回答by Vidyarani Shinde
code extract without using iterator
import java.util.ArrayList;
import java.util.List;
public class Test {
final static List<String> str = new ArrayList<String>();
public Test(){
str.add("A");
str.add("B");
str.add("C");
str.add("C");
str.add("D");
str.add("A");
str.add("B");
str.add("C");
str.add("C");
str.add("D");
str.add("B");
str.add("C");
str.add("B");
str.add("C");
str.add("C");
str.add("D");
str.add("B");
str.add("C");
str.add("C");
str.add("C");
str.add("D");
System.out.println(str);
}
public List<String> rmovedDuplicate(List<String> str){
List<String> finalList = new ArrayList<String>();
for(int i =0; i<str.size();i++){
for (int j=i+1; j<str.size();j++){
if(str.get(i).equals(str.get(j))){
str.remove(j);
i=0;
}
}
}
System.out.println("final list :"+str);
return str;
}
public static void main(String args[]){
Test t = new Test();
t.rmovedDuplicate(str);
}
}
回答by Kishor Raskar
Another simple way of doing it is as below.
另一种简单的方法如下。
import java.util.HashSet;
import java.util.List;
import java.util.Set;public class Main {
/**
* @param args
*/
public static void main(String args[]) throws SQLException {
System.out.println("Entered Main");
Test();
System.out.println(str);
set.addAll(str);
System.out.println(set);
str.clear();
str.addAll(set);
System.out.println(str);
}
final static List<String> str = new ArrayList<String>();
final static Set<String> set = new HashSet<String>();
public static void Test(){
str.add("A");
str.add("B");
str.add("C");
str.add("C");
str.add("D");
str.add("A");
str.add("B");
str.add("C");
str.add("C");
str.add("D");
str.add("B");
str.add("C");
str.add("B");
str.add("C");
str.add("C");
str.add("D");
str.add("B");
str.add("C");
str.add("C");
str.add("C");
str.add("D");
System.out.println(str);
}
Test method to populate the list is copied from Vidyarani Shinde's answer.
填充列表的测试方法是从 Vidyarani Shinde 的答案中复制的。
回答by Daniel Adenew
very simple
很简单的
way is ..first to check the list has that value if so ,skip adding it if not add the element and u get your unique list...instead of running intensive Iterator operation :)
way is ..first to check the list has that value if so ,skip adding it if not add the element and u get your unique list...instead of running intensive Iterator operation :)
Example
Example
List<Integer> listOfUserIds = new ArrayList<Integer>();
Integer UserIdCheck = 0;
for (User userTest : userCollection) {
UserIdCheck = userService.getUserByRegionCode(userTest. .getRegionId());
if (!listOfUserIds.contains(UserIdCheck)) //check befor adding listOfUserIds.add(UserIdCheck);
}
}
return listOfUserIds.toString().replace("[", "").replace("]", ""); // if u like can remove [ and ] from the list and simply return a string like "4,5,6"
回答by Rizwan Khan
I have used both advanced for each and also tried by converting ArrayList
to HashSet
and again to ArrayList
. Both of the solution works fine. You can choose any one
我都用了先进的每个并通过转换试图ArrayList
到HashSet
并再次ArrayList
。两种解决方案都可以正常工作。你可以选择任何一个
public static void main(String[] args) {
ArrayList<String> wordDulicate = new ArrayList<String>();
wordDulicate.add("Tom");
wordDulicate.add("Jones");
wordDulicate.add("Sam");
wordDulicate.add("Jamie");
wordDulicate.add("Robie");
wordDulicate.add("Helen");
wordDulicate.add("Helen");
wordDulicate.add("Helen");
wordDulicate.add("Helen");
wordDulicate.add("Tom");
wordDulicate.add("Troy");
wordDulicate.add("Mika");
wordDulicate.add("Tom");
System.out.println("Array List size"+wordDulicate.size());
ArrayList<String> nonDuplicat=new ArrayList<String>(new HashSet<String>(wordDulicate));
System.out.println("Array List size"+nonDuplicat.size());
ArrayList<String> nonDuplicatThroughIterator=new ArrayList<String>();
for(String each:wordDulicate){
if(!nonDuplicatThroughIterator.contains(each))
nonDuplicatThroughIterator.add(each);
}
System.out.println("Array List size"+nonDuplicatThroughIterator.size());
}
回答by allyson
Assume that ArrayList
implements ListADT
, that the ArrayList
and ArrayListIterator
classes are implemented as expected, and that BadListException
is an unchecked exception with a zero-argument constructor. Assume also that null elements may not be added to a list.
假设ArrayList
implements ListADT
、ArrayList
和ArrayListIterator
类按预期实现,并且这BadListException
是一个带有零参数构造函数的未经检查的异常。还假设不能将空元素添加到列表中。
I have to complete the Java method specified below, making use of iterators. My solution should meet these requirements:
我必须使用迭代器完成下面指定的 Java 方法。我的解决方案应满足以下要求:
- must explicitly use iterators for traversing lists (i.e., you may not use a for-loop or Java's extended-for loop)
- must not use the
contains
method - may use any
ListADT
methods (exceptcontains
) described in the on-line reading,includingListADT.iterator()
, but must not use any otherList
methods not mentioned there - must not modify the contents of the parameters.
- 必须显式地使用迭代器来遍历列表(即,您不能使用 for 循环或 Java 的扩展 for 循环)
- 不得使用该
contains
方法 - 可以使用在线阅读中描述的任何
ListADT
方法(除了contains
),包括ListADT.iterator()
,但不得使用List
此处未提及的任何其他方法 - 不得修改参数内容。
The skeleton of the function:
函数的骨架:
public static ListADT<String> union(ListADT<String> list1, ListADT<String> list2) {
// If list1 or list2 (or both list1 and list2) is null, throw a BadListException.
// If list1 and list2 are both empty, return a new empty list.
// If list1 is empty (but not list2), return a new list containing the strings in
// list2 with all duplicates removed.
// If list2 is empty (but not list1), return a new list containing the strings in
// list1 with all duplicates removed.
// Otherwise, create and return a new list that contains the strings in list1 and
// the strings in list2 with all duplicates removed.
//
// Examples:
// list1: "a","b","c" list2: "d","e","f" result: "a","b","c","d","e","f"
// list1: "a","c","b","d" list2: "e","d","a","f" result: "a","c","b","d","e","f"
// list1: "a","b","c","b","a" list2: "c","a","b" result: "a","b","c"
//
// Note: the list returned does not need to be in any particular order
I have to make sure that my solution only uses the methods that are in the ListADT
interface described in the on-line reading (including an iterator method, as mentioned above).
我必须确保我的解决方案只使用ListADT
在线阅读中描述的接口中的方法(包括迭代器方法,如上所述)。
How can I do this?
我怎样才能做到这一点?