很遗憾,没有。 ArrayLists 不能被有效地搜索。它们用于存储数据而不是搜索数据。如果您只想知道是否包含某个项目,我建议您使用HashSet,因为对于 ArrayList,查找的时间复杂度为 O(1) 而不是 O(n)(假设您已经实现了一个功能equals 对象的方法)。
如果您想快速搜索对象,我建议使用Dictionnary 的实现,例如HashMap。如果您能负担得起空间要求,您可以拥有多个映射,每个映射都有不同的键,以便快速查找对象,无论您必须搜索什么键。请记住,查找还需要实现正确的equals 方法。不幸的是,这要求每个密钥都是唯一的,在您的情况下这可能不是一个好主意。
但是,您可以使用HashMap为每个源存储一个以键控源作为源的节点列表。您可以对成本和目标执行相同的操作。这样,您可以大大减少需要迭代的节点数量。对于几乎没有连接的网络,这应该被证明是一个很好的解决方案。
private HashMap<Source, ArrayList<Node>> sourceMap = new HashMap<Source, ArrayList<Node>>();
private HashMap<Target, ArrayList<Node>> targetMap = new HashMap<Target, ArrayList<Node>>();
private HashMap<Cost, ArrayList<Node>> costMap = new HashMap<Cost, ArrayList<Node>>();
/** Look for a node with a given source */
for( Node node : sourceMap.get(keySource) )
{
/** Test the node for equality with a given node. Equals method below */
if(node.equals(nodeYouAreLookingFor) { return node; }
}
为了确保您的代码能够正常工作,请务必覆盖equals 方法。我知道我已经说过了,但这是一个非常常见的错误。
@Override
public boolean equals(Object object)
{
if(object instanceof Node)
{
Node node = (Node) object;
if(source.equals(node.getSource() && target.equals(node.getTarget()))
{
return true;
}
} else {
return false;
}
}
如果您不这样做,测试将简单地比较可能相等或可能不相等的引用,具体取决于您处理对象的方式。
编辑:只需阅读您的平等基础。 equals 方法应该在您的节点类中实现。但是,要使其正常工作,您还需要为源和目标实现和覆盖 equals 方法。也就是说,如果它们是对象。但请注意,如果他们也是 Nodes,这可能会导致跨整个网络的相当多的测试。
更新:添加了代码以反映 cmets 中代码的用途。
ArrayList<Node> matchingNodes = sourceMap.get(desiredSourde).retainAll(targetMap.get(desiredTarget));
现在您有了一个与源和目标条件匹配的所有节点的列表。如果你愿意牺牲一点内存,上面的查找将有 O(|sourceMap| * (|sourceMap|+|targetMap|)) [1] 的复杂度。虽然这优于所有节点的线性查找 O(|allNodeList|),但如果你的网络足够大,我认为有 1000 个节点,你会受益匪浅。如果您的网络遵循自然发生的网络,那么正如 Albert-László Barabási 所展示的,它可能是无标度的。这意味着将您的网络拆分为至少包含源和目标的列表可能(我对此没有证据)会导致这些列表的无标度大小分布。因此,我相信查找源和目标的复杂性将大大降低,因为 |sourceMap|和 |目标地图|应该大大低于|allNodeList|。