Java 8如何帮助提高HashMap的性能
这里我们将讨论如何在Java中使用HashMap时提高性能,_hashCode()契约的重要性,为什么拥有一个高效的哈希码非常重要,以及当我们使用一个低效的哈希码时会发生什么。让我们直接辗转到在我们的HashMap中实现同样的超过相同大小的键集合。具体情况如下。
实现情况: 这里没有引入这样的概念,所以在我们的HashMap上应用的是一种Native方法。
示例 1:
// 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<Student, String> 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;
}
}
输出: 它包含了大量的输出行,以说明所花费的毫秒,因此,输出卷的最后一个快照被附在下面,以便计算出所有操作所花费的时间。情况如下。
输出解释: 在上面的程序中,我们使用Student作为HashMap的键,Student类中的hashCode()重写写得非常低效,对每个Student对象都返回相同的hashcode。
为什么一个高效的哈希码如此重要?
当你运行上述程序时,幕后实际发生的情况是,当HashMap被创建时,它将所有10000个学生对象的键存储到同一个桶中。结果,所有的键都被存储在一个桶里,这导致了巨大的性能冲击,你可以看到第一个程序的执行时间大约是1700毫秒。
现在,在下面的程序中,我们在学生类中的哈希码覆盖是高效的,为每个学生对象返回唯一的哈希码。因此,每个哈希图的键被存储在一个单独的桶中,这使存储键的性能提高了’n’倍,你可以看到第二个程序的执行时间只有大约300毫秒
示例 2:
// 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<Student, String> 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秒。因此,当我们比较上述的例子时,10倍的乘数是合理的。