Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/358.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访问_Java_Performance_Java 8_Java 9_Linkedhashmap - Fatal编程技术网

Java 按索引和性能列出的LinkedHashMap访问

Java 按索引和性能列出的LinkedHashMap访问,java,performance,java-8,java-9,linkedhashmap,Java,Performance,Java 8,Java 9,Linkedhashmap,我想讨论一点特定集合LinkedHashMap针对特定需求的性能,以及Java8或Java9的新特性如何在这方面有所帮助 假设我有以下LinkedHashMap: private Map<Product, Item> items = new LinkedHashMap<>(); 解决方案2: public boolean removeItem(int position) { List<Product> orderedList = new ArrayL

我想讨论一点特定集合LinkedHashMap针对特定需求的性能,以及Java8或Java9的新特性如何在这方面有所帮助

假设我有以下LinkedHashMap:

private Map<Product, Item> items = new LinkedHashMap<>();
解决方案2:

public boolean removeItem(int position) {
    List<Product> orderedList = new ArrayList<>(items.keySet());
    Product key = orderedList.get(position);

    return items.remove(key) != null;
}
public boolean removeItem(int position) {
    int counter = 0;
    Product key = null; //assuming there's no null keys

    for(Map.Entry<Product, Item> entry: items.entrySet() ){
        if( counter == position ){
            key = entry.getKey();
            break;
        }
        counter++;
    }

    return items.remove(key) != null;
}
public boolean removietem(int位置){
int计数器=0;
Product key=null;//假设没有null键
for(Map.Entry:items.entrySet()){
如果(计数器==位置){
key=entry.getKey();
打破
}
计数器++;
}
返回项目。删除(键)!=null;
}
关于这两种解决方案的考虑

S1:我知道ArrayList具有快速迭代和访问功能,因此我认为这里的问题是正在创建一个全新的集合,因此如果我有一个巨大的集合,内存将受到影响

S2:我知道LinkedHashMap的迭代速度比HashMap快,但不如ArrayList快,因此我相信如果我们有大量的集合,而不是内存,这里的迭代时间会受到影响

考虑到所有这些,并且我的考虑是正确的,我能说这两种解决方案都有O(n)复杂性吗

使用Java8或Java9的最新特性,在性能方面是否有更好的解决方案

干杯

考虑到所有这些,并且我的考虑是正确的,我能说这两种解决方案都有O(n)复杂性吗

对。平均复杂度是相同的 在第一个解决方案中,
newarraylist(entrySet)
步骤是
O(N)

在第二种解决方案中,循环是
O(N)

不过,最佳情况的复杂性有所不同。在第一个解决方案中,始终复制整个列表。在第二种解决方案中,您只需迭代所需的次数。因此,最好的情况是它可以在第一个元素处停止迭代

但是,虽然在这两种情况下,平均复杂性都是
O(N)
,但我的直觉是,第二种解决方案将是最快的。(如果这对您很重要,请对其进行基准测试…)

使用Java8或Java9的最新特性,在性能方面是否有更好的解决方案

Java8和Java9没有提供任何性能改进

如果您想要比O(N)平均复杂度更好,则需要不同的数据结构

另一件需要注意的事情是,索引地图的条目集通常不是一件有用的事情。每当从集合中删除一个条目时,其他一些条目的索引值都会发生更改

很难有效地模仿这种“不稳定”的索引行为。如果您想要稳定的行为,那么您可以使用用于位置查找/插入/检索的
HashMap
/
LinkedHashMap
来扩充主
HashMap
。但即使这样也有点尴尬。。。考虑到如果需要在位置
i
i+1

的条目之间插入一个新条目会发生什么情况,时间复杂度是相同的,因为在这两种情况下,都是线性迭代,但效率仍然不同,因为第二个变量只会迭代到指定的元素,而不是创建一个完整的副本

您可以通过在找到条目后不执行额外的查找来进一步优化此功能。要使用指向
映射中实际位置的指针
,必须使用其
迭代器
显式:

public boolean removeItem(int position) {
    if(position >= items.size()) return false;
    Iterator<?> it=items.values().iterator();
    for(int counter = 0; counter < position; counter++) it.next();
    boolean result = it.next() != null;
    it.remove();
    return result;
}
您可以使用流API检索特定元素,但是后续的
remove
操作需要进行查找,这会降低在迭代器上调用
remove
的效率,因为对于大多数实现,迭代器已经有了对映射中位置的引用

public boolean removeItem(int position) {

    if(position >= items.size() || position < 0)
        return false;

    Product key = items.keySet().stream()
        .skip(position)
        .findFirst()
        .get();

    items.remove(key);
    return true;
}
public boolean removietem(int位置){
如果(位置>=items.size()| |位置<0)
返回false;
产品密钥=items.keySet().stream()
.跳过(位置)
.findFirst()
.get();
项目。移除(键);
返回true;
}

您使用的数据结构不符合您的要求。任何类型的散列映射都没有位置索引。@EJP我知道映射不能通过索引访问,我简化了问题,碰巧同一个类应该有removeItem(Product Product)和removeItem(int position)。报告了滥用情况。保留您的个人评论。@EJP为什么删除其他评论?当然,为什么不用迭代器链接for循环-我喜欢!!你好,霍尔格,我想为这个案例添加一个使用流的解决方案。正如我在问题中提到的,我想知道是否可以使用Java8新库来实现这一点。@skinny_jones您只需将您的编辑作为答案发布即可。就目前情况而言,您只是在添加答案,这与霍尔格的建议大不相同。@skinny_jones我从您的代码中删除了不必要的内容。无需检查
项。size()==0
,因为
位置>=items.size()| |位置<0
在这种情况下已为真。此外,当您只需要密钥时,不要在
entrySet()
后面加上
.map(e->e.getKey())
,因为您可以首先在
keySet()上进行流式处理。当你想要得到第一个元素时,不要收集到一个列表中。使用
findFirst()
时,
限制(1)
将过时。在这两种情况下,当不使用
迭代器进行删除时,删除操作意味着另一次查找。“不稳定的索引行为”不是
LinkedHashMap
特定的事情。从
列表中删除元素时,所有后续元素也将更改其索引。尽管如此,没有人会说索引列表的元素不是一件有用的事情……是的。。。但至少按索引查找是有效的。
public boolean removeItem(int position) {

    if(position >= items.size() || position < 0)
        return false;

    Product key = items.keySet().stream()
        .skip(position)
        .findFirst()
        .get();

    items.remove(key);
    return true;
}