Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/395.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 列表中hashCode()的JVM优化_Java_List_Optimization_Hash_Jvm - Fatal编程技术网

Java 列表中hashCode()的JVM优化

Java 列表中hashCode()的JVM优化,java,list,optimization,hash,jvm,Java,List,Optimization,Hash,Jvm,想象一个简单的例子: class B{ public final String text; public B(String text){ this.text = text; } } class A { private List<B> bs = new ArrayList<B>; public B getB(String text){ for(B b :bs){ if(b.te

想象一个简单的例子:

class B{
    public final String text;
    public B(String text){
        this.text = text;
    }
}

class A {
    private List<B> bs = new ArrayList<B>;

    public B getB(String text){
        for(B b :bs){
           if(b.text.equals(text)){
               return b;
           }
        }
        return null;
    }

    [getter/setter]
}
B类{
公共最终字符串文本;
公共B(字符串文本){
this.text=文本;
}
}
甲级{
私有列表bs=新的ArrayList;
公共B getB(字符串文本){
(B:bs){
如果(b.text.equals(text)){
返回b;
}
}
返回null;
}
[getter/setter]
}
假设对于A的每个实例,
列表
都是大的,我们需要经常调用
getB(String)
。但是,假设列表也可以更改(添加/删除元素,甚至重新分配)

在这个阶段,getB(String)的平均复杂度是O(n)。为了改进这一点,我想知道我们是否可以使用一些聪明的缓存

假设我们将
列表
缓存在
映射
中,其中键是
B.text
。这将提高性能,但如果列表被更改(新元素或已删除元素)或重新分配(
A.bs
指向一个新引用),则它将不起作用

为了解决这个问题,我认为,与
Map
一起,我们可以存储列表
bs
的散列。当我们调用
getB(String)
方法时,我们计算列表
bs
的哈希值。如果哈希没有改变,我们从映射中获取结果,如果改变了,我们重新加载映射

问题在于,计算
java.util.List
的哈希值会遍历列表的所有元素,并计算它们的哈希值,至少是O(n)

问题

我想知道的是,JVM计算列表哈希的速度是否会比在
getB(String)
方法中执行循环更快。这可能取决于
B
的哈希实现。如果是这样的话,什么样的事情可以奏效?简而言之,我想知道这是愚蠢的还是可以带来一些性能改进

如果是这样的话,什么样的事情可以奏效

简单地说:在你不知道的情况下,不要让任何事情改变你的清单。我怀疑您目前有以下情况:

public List<String> getAllBs() {
    return bs;
}
public List getAllBs(){
返回bs;
}
。。。和一个类似的二传手。如果您停止这样做,而只是使用适当的变异方法,那么您可以确保您的代码是唯一变异列表的代码。。。这意味着你可以记住你的地图是“脏的”,或者只是在改变列表的同时改变地图

如果是这样的话,什么样的事情可以奏效

简单地说:在你不知道的情况下,不要让任何事情改变你的清单。我怀疑您目前有以下情况:

public List<String> getAllBs() {
    return bs;
}
public List getAllBs(){
返回bs;
}

。。。和一个类似的二传手。如果您停止这样做,而只是使用适当的变异方法,那么您可以确保您的代码是唯一变异列表的代码。。。这意味着您可以记住您的地图是“脏的”,也可以在更改列表的同时更改地图。

根据您的描述,您似乎不需要
列表


列表
替换为
哈希映射
。如果需要搜索
B
s,最好的数据结构是hashmap,而不是列表

根据您的描述,您似乎不需要
列表


列表
替换为
哈希映射
。如果需要搜索
B
s,最好的数据结构是hashmap,而不是列表

您可以实现自己的类
IndexedBArrayList
,它扩展了
ArrayList

然后将此功能添加到其中:

  • 一个
    私有HashMap索引
  • 除了调用相应的超级方法外,还会重写ArrayList的所有mutator方法以保持此索引哈希映射的更新
  • 一个新的
    public B getByString(String)
    方法,它使用哈希映射

您可以实现自己的类
IndexedBArrayList
,它扩展了
ArrayList

然后将此功能添加到其中:

  • 一个
    私有HashMap索引
  • 除了调用相应的超级方法外,还会重写ArrayList的所有mutator方法以保持此索引哈希映射的更新
  • 一个新的
    public B getByString(String)
    方法,它使用哈希映射

在没有解释原因的情况下,您似乎出于某种原因认为保持列表结构也很重要。唯一合理的原因是您需要保持集合顺序的一致性。如果切换到“普通”映射,则值的顺序不再是恒定的,例如,保持在向映射添加项目的顺序

如果您既需要保持顺序(列表行为)又需要使用键访问单个项目,则可以使用
LinkedHashMap
,它本质上连接了
LinkedList
HashMap
的行为。即使
LinkedHashMap.values()
返回的是一个集合而不是一个列表,列表行为也会在集合中得到保证


您的问题的另一个问题是,您不能使用列表的哈希代码来安全地确定更改。如果哈希代码已更改,则确实可以确定列表也已更改。如果两个哈希代码相同,您仍然无法确保列表实际上是相同的。例如,如果哈希代码实现基于字符串,“1a”和“2B”的哈希代码是相同的。

在没有实际解释原因的情况下,出于某种原因,您似乎认为保留列表结构也是必要的。唯一合理的原因是您需要保持集合顺序的一致性。如果切换到“普通”贴图,则值的顺序不再是恒定的,例如,保持在您添加的顺序中