Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/195.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 数据结构ArrayList中的高效搜索_Java_Android_Search_Data Structures_Quadtree - Fatal编程技术网

Java 数据结构ArrayList中的高效搜索

Java 数据结构ArrayList中的高效搜索,java,android,search,data-structures,quadtree,Java,Android,Search,Data Structures,Quadtree,我有一个包含节点的ArrayList。节点具有来源、目标和成本。现在我必须迭代整个ArrayList。这会持续超过1000个节点。因此,我尝试按来源对列表进行排序。但是为了在列表中找到对应的一对,我尝试了二进制搜索。不幸的是,只有当我想比较源或目标时,这才有效。但我必须对两者进行比较,才能找到合适的一对。是否还有其他可能搜索ArrayList 您需要将源和目标合并到一个比较器中,例如 compare(T o1, T o2) { if(o1.source < o2.source) {

我有一个包含节点的ArrayList。节点具有来源、目标和成本。现在我必须迭代整个ArrayList。这会持续超过1000个节点。因此,我尝试按来源对列表进行排序。但是为了在列表中找到对应的一对,我尝试了二进制搜索。不幸的是,只有当我想比较源或目标时,这才有效。但我必须对两者进行比较,才能找到合适的一对。是否还有其他可能搜索ArrayList

您需要将源和目标合并到一个比较器中,例如

compare(T o1, T o2) {
    if(o1.source < o2.source) { return -1; }
    else if(o1.source > o2.source) { return 1; }
    // else o1.source == o2.source
    else if(o1.target < o2.target) { return -1; }
    else if(o1.target > o2.target) { return 1; }
    else return 0;
}
比较(tO1,tO2){ if(o1.sourceo2.source){return 1;} //else o1.source==o2.source else如果(o1.targeto2.target){return 1;} 否则返回0; }
您可以使用
.compareTo()
方法来比较节点。

您可以创建两个ArrayList。第一个按源排序,第二个按目标排序。
然后,您可以使用相应列表上的binarySearch按源或目标进行搜索。

不幸的是,没有。
ArrayList
s不能有效搜索。它们用于存储数据,而不是搜索数据。如果您只想知道是否包含一个项,我建议您使用
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方法应该在节点类中实现。但是,要使其工作,还需要为源和目标实现并重写equals方法。也就是说,如果它们是对象。但是要注意,如果它们也是
节点
s,这可能会导致相当多的测试跨越整个网络

更新:添加代码以反映注释中代码的用途

ArrayList<Node> matchingNodes = sourceMap.get(desiredSourde).retainAll(targetMap.get(desiredTarget));
ArrayList matchingNodes=sourceMap.get(desiredSourde.retainal(targetMap.get(desiredTarget));

现在,您有了一个匹配源和目标条件的所有节点的列表。如果您愿意牺牲一点内存,上述查找的复杂性将为O(| sourceMap |*(| sourceMap |+| targetMap |))。虽然这比所有节点的线性查找要好,O(| allNodeList |),但如果您的网络足够大(我认为它有1000个节点),您可能会受益匪浅。如果你的网络遵循一个自然发生的网络,那么正如阿尔伯特·拉斯洛·巴拉巴西(Albert-LászlóBarabási)所示,它很可能是无标度的。这意味着,将您的网络拆分为至少包含源和目标的列表可能(我没有证据证明这一点)会导致这些列表的无标度大小分布。因此,我相信查找源和目标的复杂性将大大降低,因为| sourceMap |和| targetMap |应该大大低于| allNodeList |。

您可以创建一个帮助器类来存储源-目标对:

class SourceTarget {

    public final Source source; // public fields are OK when they're final and immutable.
    public final Target target; // you can use getters but I'm lazy
                                // (don't give this object setters. Map keys should ideally be immutable)

    public SourceTarget( Source s, Target t ){
        source = s;
        target = t;
    }

    @Override
    public boolean equals( Object other ){
        // Implement in the obvious way (only equal when both source and target are equal
    }

    @Override
    public int hashCode(){
        // Implement consistently with equals
    }
}
然后将您的东西存储在一个
HashMap
中,每个源目标对都映射到恰好具有该源目标对的节点列表。 取回

List<Node> results = map.get( new SourceTarget( node.source, node.target ) );
List results=map.get(新的SourceTarget(node.source,node.target));


除了创建帮助器类,您还可以使用Zim Zam答案中的比较器和一个
树形图
,其中一个具有代表性的
节点
对象充当
源目标
对。

如何进行搜索?您必须匹配这对中的两个项目吗?或者您需要能够搜索只匹配每对中一项的记录?我在提供的答案中添加了一些代码。我希望它将证明是有用的!数据来自哪里?您在1000个节点中使用的数据,您从何处获取?如果您认为这些数据对您有好处,请检查答案并接受其中一个?如果没有,请留下进一步的评论!我用compareTo()进行了尝试,但我需要确保源和目标与我要比较的节点中的相同。因此,不可能用compareTo()来实现。这实际上不是我想要的。我现在创建了一张地图。现在我有一个节点,源=3,目标=6,因此我必须搜索,找到唯一一个元素,它的源为3,目标为6。因为也可以有一个源为3、目标为8的节点。由于错误,重新发布了注释!是的,但是您必须搜索的集合大大减少了。我的建议是,您按照我提到的方式进行尝试,然后执行以下操作:获取源为3的所有节点集,获取目标为8的所有节点,获取两个集的交点。然后,您将拥有一个包含所有节点的集合,其中源节点为3,目标节点为8。对于交叉点,请看一看Java的retainAll(List)方法。如果你愿意,我可以举个例子
List<Node> results = map.get( new SourceTarget( node.source, node.target ) );