Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/349.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 如何使用LinkedHashMap获取submap?_Java_Performance_Dictionary_Iteration - Fatal编程技术网

Java 如何使用LinkedHashMap获取submap?

Java 如何使用LinkedHashMap获取submap?,java,performance,dictionary,iteration,Java,Performance,Dictionary,Iteration,目前,我正在使用TreeMap存储一些x和y坐标,但与ArrayList或HashMap相比,迭代非常缓慢。我之所以使用它,是因为我需要subMap()方法,这样即使精确的X值(键)不存在,我也可以在确定的范围内获得X值 LinkedHashMap的速度几乎与HashMap相同,我可以按插入顺序迭代键(我需要插入顺序或比较器顺序,就像在TreeMap中那样),但我没有submap()方法。在树状图中,我可以快速生成子图 是否有任何数据结构或某种方式可以比TreeMap更快地存储有序值(通过插入顺

目前,我正在使用
TreeMap
存储一些x和y坐标,但与
ArrayList
HashMap
相比,迭代非常缓慢。我之所以使用它,是因为我需要
subMap()
方法,这样即使精确的X值(键)不存在,我也可以在确定的范围内获得X值

LinkedHashMap
的速度几乎与
HashMap
相同,我可以按插入顺序迭代键(我需要插入顺序或比较器顺序,就像在TreeMap中那样),但我没有
submap()
方法。在树状图中,我可以快速生成子图


是否有任何数据结构或某种方式可以比TreeMap更快地存储有序值(通过插入顺序或比较器),即使精确值不在映射中,也可以在一定范围内获取子映射?我的意思是,也许我想要2到25之间的值,但是2不存在,最近的值是3,所以它将返回一个从3到25的子映射。或者以某种方式将此功能添加到
LinkedHashMap

听起来你需要一个树形图,它的迭代速度不比LinkedHashMap慢多少,并且做你真正想要的事情。由于HashMap是无序的,subMap没有任何意义。

今天我终于找到了问题的答案。经过几次测试,
HashMap
LinkedHashMap
TreeMap
ArrayList
慢得多,我想使用它们只是为了能够创建
submap()
。因此,我创建了一个扩展
ArrayList
的新类,它给了我一个非常好的性能,在answer的帮助下,我创建了一个快速的方法,通过值而不是索引获取子列表。以下是完整的课程:

/**
 * The purpose of this class is to be a faster replacement to a {@link java.util.TreeMap} with
 *  the ability to get sublist containing a range of x values. ArrayList access time is O(1) while
 *  {@link java.util.TreeMap} is O(log(n)). When large data is handled the impact on performance is
 *  noticeable.
 */
public class XYDataset extends ArrayList<PointValue> {

    private final float COMPARISON_THRESHOLD = 0.01f;

    final Comparator<PointValue> comparator = new Comparator<PointValue>() {
        @Override
        public int compare(PointValue lhs, PointValue rhs) {
            if (Math.abs(lhs.getX() - rhs.getX()) < COMPARISON_THRESHOLD) return 0;
            return lhs.getX() < rhs.getX() ? -1 : 1;
        }
    };

    public XYDataset(int capacity) {
        super(capacity);
    }

    public XYDataset() {
    }

    public XYDataset(Collection<? extends PointValue> collection) {
        super(collection);
    }

    @Override
    public List<PointValue> subList(int start, int end) {
        return super.subList(start, end);
    }

    /**
     * Generate a sublist containing the range of x values passed
     * @param x1 lower x value
     * @param x2 upper x value
     * @return sublist containing x values from x1 to x2
     */
    public List<PointValue> subList(float x1, float x2){
        /**
         * Collections.binarySearch() returns the index of the search key, if it is contained in the list;
         *  otherwise it returns (-(insertion point) - 1).
         * The insertion point is defined as the point at which the key would be inserted into the list:
         *  the index of the first element greater than the key, or list.size() if all elements in the list
         *  are less than the specified key. Note that this guarantees that the return value will be >= 0 if
         *  and only if the key is found.
         */
        int n1 = Collections.binarySearch(this, new PointValue(x1, 0), comparator);
        int n2 = Collections.binarySearch(this, new PointValue(x2, 0), comparator);

        /**
         * Example, we assume the list is sorted. Based on (https://stackoverflow.com/questions/19198586/search-sorted-listlong-for-closest-and-less-than)
         *
         * long X = 500;
         * List<Long> foo = new Arraylist<>();
         * foo.add(450L);
         * foo.add(451L);
         * foo.add(499L);
         * foo.add(501L);
         * foo.add(550L);
         *
         * If we search for something that isn't in the list you can work backward from the return value
         *  to the index you want. If you search for 500 in your example list, the algorithm would return (-3 - 1) = -4.
         * Thus, you can add 1 to get back to the insertion point (-3), and then multiply by -1 and subtract 1 to get
         *  the index BEFORE the first element GREATER than the one you searched for, which will either be an index that
         *  meets your 2 criteria OR -1 if all elements in the list are greater than the one you searched for.
         */
        if(n1 < 0) n1 = -n1-1;
        if(n2 < 0) n2 = -n2-1;

        return this.subList(n1, n2);
    }
}
/**
*这个类的目的是更快地替换{@link java.util.TreeMap},使用
*获取包含x值范围的子列表的能力。ArrayList访问时间为O(1),而
*{@link java.util.TreeMap}是O(log(n))。在处理大数据时,对性能的影响很小
*显而易见。
*/
公共类XYDataset扩展了ArrayList{
私人最终浮动比较_阈值=0.01f;
最终比较器比较器=新比较器(){
@凌驾
公共整数比较(点值lhs、点值rhs){
if(Math.abs(lhs.getX()-rhs.getX())public XYDataset(CollectionI当前正在使用TreeMap,但与具有O(1)的HashMap或ArrayList相比,它的速度非常慢 access@Andres关注的是访问时间还是迭代时间?是迭代时间,我迭代了500k个条目。但是如果访问时间较低,迭代时间应该较低还是不低?@Andres迭代与随机访问是不同的操作,我不希望它是相同的。