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 毫秒。
Now, in the program below, our hashcode override in the Student class is efficient and returns unique hashcode for every Student Object. As a result, each hashmap key is stored in a separate bucket, which improves the performance by ‘n’ times for storing the keys, and you can see that the time taken for the execution of the second program is only about 300 milliseconds
示例 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 的乘数是合理的。