我们可以创建哈希映射键单例吗?
Can we create hashmap key singleton?
前几天我在面试,问到hashmap的时候哑口无言
这里有几个
能把key做成单例吗?
我们能否使 hashmap 的键可变或不可变,您会选择哪一个,为什么?
对于第二个问题,我通过网络搜索发现,如果我们正在创建密钥,它应该是不可变的,否则数据将保存在第一个密钥上,然后在稍后修改,如果我们再次尝试获取它,它将返回 null,因此对象将是丢失。
这是我为此 Custom Key Hashmap
遵循的 link
关于第一个问题,我们可以创建 Hashmap 键单例吗,根据我的说法,如果我们创建键单例,那么如果我们尝试使用单例键添加,我们将失去使用相同键的哈希图的能力将替换数据。
请多多关照。
嗯,这很有趣。
首先,Java中的单例Class是一个class,一次只能有一个对象(class的一个实例)。
这意味着只有一个副本在多个对象之间共享。
我们有两个单例对象class
Singleton x = Singleton.getInstance();
Singleton y = Singleton.getInstance();
场景 1:如果我们使用 Singleton 键创建 HashMap 那么
Map<SingletonClass, Interger> map = new HashMap<>();
map.put(x, 10);
map.put(y, 20);
你认为输出会是什么,
在这种情况下,大小为 1,10 被 20 覆盖。对吗?
相同的对象具有相同的 HashCode 和 equals 方法实现。
场景 2:如果一个对象只是更改 Singleton 字段的值会怎么样 class
Map<SingletonClass, Interger> map = new HashMap<>();
map.put(x, 10);
y.s = (y.s).toUpperCase(); // s is a String field in Singleton Class
map.put(y, 20);
在这种情况下,大小为 1。x 和 y 的哈希码相同。
因此,总是有 1 个对象会一次又一次地覆盖该值。
如您所知,我们为什么使用 Immutable class 作为密钥。现在很清楚,你不能在 HashMap 中使用 Singleton class 作为键。
即使您覆盖 HashCode 对象,因为键作为引用存储在 Map 中。所以如果你改变它的实现,它会在执行 Singleton Class 的 hashcode 方法时反映在 Map 中。
是的,您可以覆盖 equals 方法,但它只会增加 HashMap 中的冲突情况。
一个非常有趣的问题,因为它需要理解究竟什么是地图...
- Can we make key as singleton?
如果您使用单例模式来生成密钥,那么显然只会创建一个密钥,然后一次只会出现一对 (key,value)地图。这就是说,我们显然更改了与唯一可能的键关联的值。这个答案当然是肯定的,关键的本质对地图来说并不重要,但这会导致地图愚蠢或不是很有用(至少给我一个有说服力的例子)。
- Can we make key of hashmap mutable or immutable which one you will
choose and why?
选择不可变!否则,根据您选择的具体地图,您将遇到严重的问题。
对于 HashMap
和类似的人:
import java.util.*;
class K {
private int value;
public boolean equals(Object o) { K k = (K)o; return k.value==value; }
public int hashCode() { return value; }
public K(int v) { this.value = v; }
public void setValue(int v) { this.value = v; }
public String toString() { return ""+value; }
}
public class Test {
public static void main(String []a) {
HashMap<K,String> m = new HashMap<K,String>();
K k1 = new K(33);
m.put(k1,"Here I am");
K k2 = new K(44);
m.put(k2,"Here it is");
System.out.println("k1: "+k1+" "+m.get(k1));
System.out.println("k2: "+k2+" "+m.get(k2));
k1.setValue(666);
System.out.println("k1: "+k1+" "+m.get(k1));
k1.setValue(44);
System.out.println("k2: "+k2+" "+m.get(k2));
k1.setValue(666);
System.out.println("k1: "+k1+" "+m.get(k1));
k1.setValue(33);
System.out.println("k1: "+k1+" "+m.get(k1));
}
}
将产生:
k1: 33 Here I am
k2: 44 Here it is
k1: 666 null
k2: 44 Here it is
k1: 666 null
k1: 33 Here I am
这自然可以理解为,object key里面的值作为map的key。
现在 TreeMap
情况有所不同:
import java.util.*;
class K implements Comparable<K> {
private int value;
public boolean equals(Object o) { K k = (K)o; return k.value==value; }
public int hashCode() { return value; }
public K(int v) { this.value = v; }
public void setValue(int v) { this.value = v; }
public String toString() { return ""+value; }
public int compareTo(K k) { return Integer.compare(value,k.value); }
}
public class Test2 {
public static void main(String []a) {
TreeMap<K,String> m = new TreeMap<K,String>();
K k1 = new K(33);
m.put(k1,"Here I am");
K k2 = new K(44);
m.put(k2,"Here it is");
System.out.println("k1: "+k1+" "+m.get(k1));
System.out.println("k2: "+k2+" "+m.get(k2));
k1.setValue(666);
System.out.println("k1: "+k1+" "+m.get(k1));
k1.setValue(44);
System.out.println("k2: "+k2+" "+m.get(k2));
k1.setValue(666);
System.out.println("k1: "+k1+" "+m.get(k1));
k1.setValue(33);
System.out.println("k1: "+k1+" "+m.get(k1));
}
}
将产生:
k1: 33 Here I am
k2: 44 Here it is
k1: 666 Here I am
k2: 44 Here I am
k1: 666 Here I am
k1: 33 Here I am
看看 k2 和值 44 现在如何访问映射中的不同值...k2
没有发生变化,但随着时间的推移检索到的值不一样!
因此,永远不要使用可变键...
前几天我在面试,问到hashmap的时候哑口无言 这里有几个
能把key做成单例吗?
我们能否使 hashmap 的键可变或不可变,您会选择哪一个,为什么?
对于第二个问题,我通过网络搜索发现,如果我们正在创建密钥,它应该是不可变的,否则数据将保存在第一个密钥上,然后在稍后修改,如果我们再次尝试获取它,它将返回 null,因此对象将是丢失。 这是我为此 Custom Key Hashmap
遵循的 link关于第一个问题,我们可以创建 Hashmap 键单例吗,根据我的说法,如果我们创建键单例,那么如果我们尝试使用单例键添加,我们将失去使用相同键的哈希图的能力将替换数据。
请多多关照。
嗯,这很有趣。
首先,Java中的单例Class是一个class,一次只能有一个对象(class的一个实例)。 这意味着只有一个副本在多个对象之间共享。
我们有两个单例对象class
Singleton x = Singleton.getInstance();
Singleton y = Singleton.getInstance();
场景 1:如果我们使用 Singleton 键创建 HashMap 那么
Map<SingletonClass, Interger> map = new HashMap<>();
map.put(x, 10);
map.put(y, 20);
你认为输出会是什么, 在这种情况下,大小为 1,10 被 20 覆盖。对吗? 相同的对象具有相同的 HashCode 和 equals 方法实现。
场景 2:如果一个对象只是更改 Singleton 字段的值会怎么样 class
Map<SingletonClass, Interger> map = new HashMap<>();
map.put(x, 10);
y.s = (y.s).toUpperCase(); // s is a String field in Singleton Class
map.put(y, 20);
在这种情况下,大小为 1。x 和 y 的哈希码相同。
因此,总是有 1 个对象会一次又一次地覆盖该值。
如您所知,我们为什么使用 Immutable class 作为密钥。现在很清楚,你不能在 HashMap 中使用 Singleton class 作为键。
即使您覆盖 HashCode 对象,因为键作为引用存储在 Map 中。所以如果你改变它的实现,它会在执行 Singleton Class 的 hashcode 方法时反映在 Map 中。 是的,您可以覆盖 equals 方法,但它只会增加 HashMap 中的冲突情况。
一个非常有趣的问题,因为它需要理解究竟什么是地图...
- Can we make key as singleton?
如果您使用单例模式来生成密钥,那么显然只会创建一个密钥,然后一次只会出现一对 (key,value)地图。这就是说,我们显然更改了与唯一可能的键关联的值。这个答案当然是肯定的,关键的本质对地图来说并不重要,但这会导致地图愚蠢或不是很有用(至少给我一个有说服力的例子)。
- Can we make key of hashmap mutable or immutable which one you will choose and why?
选择不可变!否则,根据您选择的具体地图,您将遇到严重的问题。
对于 HashMap
和类似的人:
import java.util.*;
class K {
private int value;
public boolean equals(Object o) { K k = (K)o; return k.value==value; }
public int hashCode() { return value; }
public K(int v) { this.value = v; }
public void setValue(int v) { this.value = v; }
public String toString() { return ""+value; }
}
public class Test {
public static void main(String []a) {
HashMap<K,String> m = new HashMap<K,String>();
K k1 = new K(33);
m.put(k1,"Here I am");
K k2 = new K(44);
m.put(k2,"Here it is");
System.out.println("k1: "+k1+" "+m.get(k1));
System.out.println("k2: "+k2+" "+m.get(k2));
k1.setValue(666);
System.out.println("k1: "+k1+" "+m.get(k1));
k1.setValue(44);
System.out.println("k2: "+k2+" "+m.get(k2));
k1.setValue(666);
System.out.println("k1: "+k1+" "+m.get(k1));
k1.setValue(33);
System.out.println("k1: "+k1+" "+m.get(k1));
}
}
将产生:
k1: 33 Here I am
k2: 44 Here it is
k1: 666 null
k2: 44 Here it is
k1: 666 null
k1: 33 Here I am
这自然可以理解为,object key里面的值作为map的key。
现在 TreeMap
情况有所不同:
import java.util.*;
class K implements Comparable<K> {
private int value;
public boolean equals(Object o) { K k = (K)o; return k.value==value; }
public int hashCode() { return value; }
public K(int v) { this.value = v; }
public void setValue(int v) { this.value = v; }
public String toString() { return ""+value; }
public int compareTo(K k) { return Integer.compare(value,k.value); }
}
public class Test2 {
public static void main(String []a) {
TreeMap<K,String> m = new TreeMap<K,String>();
K k1 = new K(33);
m.put(k1,"Here I am");
K k2 = new K(44);
m.put(k2,"Here it is");
System.out.println("k1: "+k1+" "+m.get(k1));
System.out.println("k2: "+k2+" "+m.get(k2));
k1.setValue(666);
System.out.println("k1: "+k1+" "+m.get(k1));
k1.setValue(44);
System.out.println("k2: "+k2+" "+m.get(k2));
k1.setValue(666);
System.out.println("k1: "+k1+" "+m.get(k1));
k1.setValue(33);
System.out.println("k1: "+k1+" "+m.get(k1));
}
}
将产生:
k1: 33 Here I am
k2: 44 Here it is
k1: 666 Here I am
k2: 44 Here I am
k1: 666 Here I am
k1: 33 Here I am
看看 k2 和值 44 现在如何访问映射中的不同值...k2
没有发生变化,但随着时间的推移检索到的值不一样!
因此,永远不要使用可变键...