我想得到集合中每两个不同元素的对。我认为,如果对每个循环使用,我必须以O(n^2(的复杂性进行迭代。如果使用迭代器,我可以有两个迭代器。第二个迭代者指向第一个迭代程序的下一个,这意味着对于第二个循环,我不必从一开始就循环。然而,我似乎无法正确打印我的方法。
public static void main(String[] args){
Set<String> s = new HashSet<String>();
s.add("A");
s.add("B");
s.add("C");
s.add("D");
Iterator<String> itr1 = s.iterator();
while (itr1.hasNext()){
Iterator<String> itr2 = itr1;
String s1 = itr1.next();
while (itr2.hasNext()){
String s2 = itr2.next();
System.out.println(s1 + " " + s2);
}
}
}
输出为
A B
A C
A D
然而,我想要的是:
A B
A C
A D
B C
B D
C D
我不认为
Iterator<String> itr2 = itr1;
做你想做的事。这意味着itr2
与itr1
实际上是相同的对象。它不是一个深度或有状态的副本。
如果你使用列表,这会更容易,因为我们可以依靠索引进行排序。为了使用Iterator
和Set
,您需要维护一个已经使用过的对象集合:
Iterator<String> itr1 = s.iterator();
Set<String> used = new HashSet<>(); // track the elements that have been used in the first column
while (itr1.hasNext()) {
Iterator<String> itr2 = s.iterator(); // a new iterator
String s1 = itr1.next();
used.add(s1); // track what we've used
while (itr2.hasNext()) {
String s2 = itr2.next();
if (used.contains(s2));
continue; // we've alread used s2
System.out.println(s1 + " " + s2);
}
}
从理论上讲,最好使用数组(或列表(和for
循环来做您想做的事情:
String[] elements = s.toArray(new String[s.size()]);
for (int i = 0; i < elements.length; ++i) {
String s1 = elements[i];
// loop through all successive elements
for (int j = i + 1; j < elements.length; ++j) {
String s2 = elements[j];
System.out.println(s1 + " " + s2);
}
}
您的一般逻辑是正确的,您的问题是行
Iterator<String> itr2 = itr1;
不复制迭代器,而是为两个循环使用相同的迭代器对象。
老实说,我认为在这种情况下,使用带有索引变量的简单for循环比使用循环迭代器要容易得多。
然而,由于您不能使用索引变量对集合进行迭代,我建议使用简单的List,或者至少将集合转换为特定函数的List:
public static void main(String[] args) {
List<String> s = new ArrayList<String>();
s.add("A");
s.add("B");
s.add("C");
s.add("D");
for (int i = 0; i < s.size(); i++) {
String s1 = s.get(i);
for (int x = i+1; x < s.size(); x++) {
String s2 = s.get(x);
System.out.println(s1 + " " + s2);
}
}
}
迭代程序itr2=itr1;将导致两个变量指向同一个interator。
1.(不要使用无序集合2.(在数组上按索引进行迭代,这样您就可以重用索引来在第一个的索引处启动内部循环