📜  Java 8 如何帮助提高 HashMap 的性能?

📅  最后修改于: 2022-05-13 01:55:03.812000             🧑  作者: Mango

Java 8 如何帮助提高 HashMap 的性能?

在这里,我们将讨论如何在Java使用HashMap提高性能, hashCode() 合约的重要性以及为什么拥有高效的哈希码非常重要,以及当我们使用低效的哈希码时会发生什么哈希码。让我们直接滚动到在 HashMap 中相同大小的键集上实现相同的。如下:

实现:这里没有引入这样的概念,所以在我们的 HashMap 上应用了一种幼稚的方法。

示例 1:

Java
// Java Program to Illustrate In-efficient Technique
// While using HashMap
  
// Importing Map and HashMap utility classes
// from java.util package
import java.util.HashMap;
import java.util.Map;
  
// Main class
class HashMapEx2 {
  
    // main driver method
    public static void main(String[] args)
    {
        // Creating a Map object
        // Declaring object of user-defined class and string
        // type
        Map studentMap = new HashMap<>();
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            studentMap.put(new Student("saty" + i),
                           "satyy" + i);
        }
        studentMap.forEach(
            (k, v) -> System.out.println(k + " : " + v));
        long endTime = System.currentTimeMillis();
        long timeElapsed = endTime - startTime;
        System.out.println(
            "\n Execution time in milliseconds for In-Efficient hashcode :  "
            + timeElapsed + " milliseconds.");
    }
}
  
/*Student class.*/
class Student {
    String name;
  
    public Student(String name)
    {
        super();
        this.name = name;
    }
  
    @Override public String toString()
    {
        return "Student [name=" + name + "]";
    }
  
    /* Very in-efficient hashcode override */
    @Override public int hashCode()
    {
        return 12; /* Very inefficient hashcode, returns 12
                      for every key, that means all the keys 
                      will end up in the same bucket */
    }
  
    @Override public boolean equals(Object obj)
    {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Student other = (Student)obj;
        if (name == null) {
            if (other.name != null)
                return false;
        }
        else if (!name.equals(other.name))
            return false;
        return true;
    }
}


Java
// Java Program to Illustrate In-efficient Technique
// While using HashMap
  
// Importing Map and HashMap utility classes
// from java.util package
import java.util.HashMap;
import java.util.Map;
  
// Main class
class HashMapEx3 {
  
    // main driver method
    public static void main(String[] args)
    {
        Map studentMap = new HashMap<>();
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            studentMap.put(new Student("saty" + i),
                           "satyy" + i);
        }
        studentMap.forEach(
            (k, v) -> System.out.println(k + " : " + v));
        long endTime = System.currentTimeMillis();
        long timeElapsed = endTime - startTime;
        System.out.println(
            "\n Execution time in milliseconds for Efficient hashCode: "
            + timeElapsed + " milliseconds");
    }
}
  
/*Student class.*/
class Student {
    String name;
    public Student(String name)
    {
        super();
        this.name = name;
    }
  
    @Override public String toString()
    {
        return "Student [name=" + name + "]";
    }
  
    /* Efficient hashcode override */
    @Override public int hashCode()
    {
        return name.hashCode()
            * 12; /* Efficient hashcode, returns unique
                hashcode for every key, that
                means the keys will be distributed into
                unique buckets */
    }
  
    @Override public boolean equals(Object obj)
    {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Student other = (Student)obj;
        if (name == null) {
            if (other.name != null)
                return false;
        }
        else if (!name.equals(other.name))
            return false;
        return true;
    }
}


输出:它包含大量的行作为输出来说明所花费的毫秒数,因此输出滚动的最后一个快照附加在下面,以计算所有操作所花费的时间。如下:



输出说明:在上面的程序中,我们使用 Student 作为 HashMap 键,并且 Student 类中的 hashCode() 重写效率非常低,它为每个 Student 对象返回相同的哈希码。

为什么高效的哈希码如此重要?

当你运行上面的程序时,幕后实际发生的事情是,当 HashMap 被创建时,它将学生对象的所有 10000 个键存储到同一个桶中。结果,所有键都存储在一个存储桶中,这导致了巨大的性能损失,您可以看到执行第一个程序所花费的时间约为 1700 毫秒。

示例 2:

Java

// Java Program to Illustrate In-efficient Technique
// While using HashMap
  
// Importing Map and HashMap utility classes
// from java.util package
import java.util.HashMap;
import java.util.Map;
  
// Main class
class HashMapEx3 {
  
    // main driver method
    public static void main(String[] args)
    {
        Map studentMap = new HashMap<>();
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 10000; i++) {
            studentMap.put(new Student("saty" + i),
                           "satyy" + i);
        }
        studentMap.forEach(
            (k, v) -> System.out.println(k + " : " + v));
        long endTime = System.currentTimeMillis();
        long timeElapsed = endTime - startTime;
        System.out.println(
            "\n Execution time in milliseconds for Efficient hashCode: "
            + timeElapsed + " milliseconds");
    }
}
  
/*Student class.*/
class Student {
    String name;
    public Student(String name)
    {
        super();
        this.name = name;
    }
  
    @Override public String toString()
    {
        return "Student [name=" + name + "]";
    }
  
    /* Efficient hashcode override */
    @Override public int hashCode()
    {
        return name.hashCode()
            * 12; /* Efficient hashcode, returns unique
                hashcode for every key, that
                means the keys will be distributed into
                unique buckets */
    }
  
    @Override public boolean equals(Object obj)
    {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Student other = (Student)obj;
        if (name == null) {
            if (other.name != null)
                return false;
        }
        else if (!name.equals(other.name))
            return false;
        return true;
    }
}

输出:它包含大量的行作为输出,以说明所花费的毫秒数,输出滚动的最后一个快照附在下面,以计算所有操作所花费的时间。如下:

我们可以找出一个显着的变化,其中示例 1 花费了接近 1700 毫秒,而这里如输出所示,它只花费了接近 180 秒。因此,当我们比较上述示例时,10X 的乘数是合理的。