将每个项目与 ArrayList 中的每个其他项目进行比较
Posted
技术标签:
【中文标题】将每个项目与 ArrayList 中的每个其他项目进行比较【英文标题】:Compare every item to every other item in ArrayList 【发布时间】:2011-06-27 00:18:35 【问题描述】:我遇到了一个我认为应该很简单的问题。
我需要将 arrayList 中的每个项目与列表中的每个其他项目进行比较,而不需要将项目与它们自己进行比较。它不像调用 equals() 比较那么简单,它涉及一些我在下面的代码中省略的自定义逻辑。此外,不应以任何方式更改 ArrayList。
我似乎遇到的问题是,一旦我进入第二个循环,我不知道我是否还有另一个对象可以比较(因为它是一个可变大小的列表)。
for(int i =0; i< list.size(); i++)
//get first object to compare to
String a = list.get(i).getA();
Iterator itr = list.listIterator(i + 1 ); // I don't know if i + 1 is valid
while(itr.hasNext())
// compare A to all remaining items on list
我认为我可能以错误的方式处理此问题,我愿意接受有关如何更好地执行此操作的建议或提示。
【问题讨论】:
您说 ArrayList 不应以任何方式更改,因此列表的大小不是可变的:它是恒定的。因此,i+1 将是 listIterator() 的有效索引,因为 i 保证为 太棒了,这个问题对我帮助很大! 在CR,这可能适合不像看起来那么容易类别(尤其是非对称compare
和一般java.util.List<>
。从compare every item in [a List L] with every other item in [L]
【参考方案1】:
你可以这样做。
for (int i = 0; i < arrayList.size(); i++)
for (int j = 0; j < arrayList.size(); j++)
if (i!=j && arrayList.get(i).YourObjectItem().equals(arrayList.get(j).YourObjectItem()))
//Your code will be here
【讨论】:
【参考方案2】:在某些情况下,这是最好的方法,因为您的代码可能已更改某些内容,而 j=i+1 不会检查。
for (int i = 0; i < list.size(); i++)
for (int j = 0; j < list.size(); j++)
if(i == j)
//to do code here
continue;
【讨论】:
一种对compare every item in [a List L] with every other item in [L]
的解释。可能是时候考虑/提出基于 java.util.stream
的方法了 - 可惜 Stream 必须是可克隆的,并提供与 Iterator 一样有用的 equals()
。【参考方案3】:
这段代码帮助我实现了这种行为:对于列表 a、b、c,我应该比较 ab、ac 和 bc,但任何其他对都将是多余的/不需要。
import java.util.*;
import static java.lang.System.out;
// rl = rawList; lr = listReversed
ArrayList<String> rl = new ArrayList<String>();
ArrayList<String> lr = new ArrayList<String>();
rl.add("a");
rl.add("b");
rl.add("c");
rl.add("d");
rl.add("e");
rl.add("f");
lr.addAll(rl);
Collections.reverse(lr);
for (String itemA : rl)
lr.remove(lr.size()-1);
for (String itemZ : lr)
System.out.println(itemA + itemZ);
循环如下图所示: Triangular comparison visual example
或者这样:
| f e d c b a
------------------------------
a | af ae ad ac ab ·
b | bf be bd bc ·
c | cf ce cd ·
d | df de ·
e | ef ·
f | ·
总比较是一个三角数 (n * n-1)/2
【讨论】:
【参考方案4】:下面的代码将使用 contains() 方法将每个项目与其他项目列表进行比较。for 循环的长度必须大于更大列表的 size(),然后才会比较两个列表的所有值。
List<String> str = new ArrayList<String>();
str.add("first");
str.add("second");
str.add("third");
List<String> str1 = new ArrayList<String>();
str1.add("first");
str1.add("second");
str1.add("third1");
for (int i = 0; i<str1.size(); i++)
System.out.println(str.contains(str1.get(i)));
输出为真 真的 假的
【讨论】:
【参考方案5】:for (int i = 0; i < list.size(); i++)
for (int j = i+1; j < list.size(); j++)
// compare list.get(i) and list.get(j)
【讨论】:
这将进行比要求更多的比较,您将测试 item1 == item3 和 item3 == item1 是的,刚刚意识到它在做一些不必要的比较,更新了代码。 @Mike 不,因为内循环只接受外循环中当前索引“后面”的元素。 我一开始初始化 j = 0,然后修复它。 是的,这确实有效,我不确定我为什么要尝试使用迭代器,我认为这是获取子列表的唯一方法。解决方案很简单,我只是在想这个。谢谢【参考方案6】:在内部使用for
循环有什么问题,就像在外部一样?
for (int j = i + 1; j < list.size(); ++j)
...
一般来说,从 Java 5 开始,我只使用过一次或两次迭代器。
【讨论】:
你应该阅读 Effective Java item 46,它明确建议不要使用传统的 for 循环(尽可能) @Sean Patrick Floyd,如果需要,JVM 可以为此使用内在函数。我现在不说它确实使用但迭代器是最容易优化的东西(通过逃逸分析) @bestsss 我不是在谈论有效的字节码(在这种情况下,Josh Bloch 也不是),而是关于可读且不易出错的源代码以上是关于将每个项目与 ArrayList 中的每个其他项目进行比较的主要内容,如果未能解决你的问题,请参考以下文章
ArrayList、for 循环和 if 语句的问题 - 为列表中的每个项目打印行
制作 ListView 时遇到问题,其中每个项目都显示模型的 ArrayList