IdentityHashMap实现Map接口使用哈希表,在比较键(和值)时使用reference-equality代替object-equality。此类不是通用 Map 实现。虽然此类实现了 Map 接口,但它故意违反了 Map 的一般契约,该契约要求在比较对象时使用 equals() 方法。当用户需要通过引用比较对象时使用该类。它属于java.util包。
IdentityHashMap的特点
- 它遵循引用相等性,而不是使用 equals() 方法,而是使用 == 运算符。
- 它不同步,必须外部同步。
- 迭代器是fail-fast,抛出ConcurrentModificationException尝试在迭代时进行修改。
- 假设系统身份哈希函数 (System.identityHashCode(Object)) 在存储桶中正确分散元素,此类为基本操作(获取和放置)提供恒定时间性能。 IdentityHashMap 不使用 hashCode() 方法,而是使用 System.identityHashCode() 方法。这是一个显著的区别,因为现在您可以使用可变对象作为 Map 中的键,当映射存储在 IdentityHashMap 中时,其哈希代码可能会发生变化。
声明:
public class IdentityHashMap<K,?V> extends AbstractMap<K,?V> implements Map<K,?V>, Serializable, Cloneable
这里,K 是键对象类型,V 是值对象类型。
在Java中,IdentityHashMap是一个实现Map接口的类。它与 HashMap 类类似,主要区别在于 IdentityHashMap 在比较键时使用引用相等而不是对象相等。
HashMap 使用 equals() 方法来比较键,而 IdentityHashMap 使用 == 运算符来比较键。这意味着在 IdentityHashMap 中,当且仅当两个键是同一对象时才被视为相等,而不是其内容相等。
以下是如何在 Java 中使用 IdentityHashMap 的示例:
Java
import java.util.IdentityHashMap;
public class Example {
public static void main(String[] args) {
IdentityHashMap<String, Integer> identityHashMap = new IdentityHashMap<>();
identityHashMap.put("A", 1);
identityHashMap.put(new String("A"), 2);
System.out.println(identityHashMap.size()); // 2
System.out.println(identityHashMap.get("A")); // 1
}
}
输出;
2
1
Java 中的 IdentityHashMap 类是 Map 接口的基于哈希表的实现,在比较键(和值)时使用 reference-equality 代替 object-equality。
使用 IdentityHashMap 相对于 HashMap 的优点:
- 查找速度更快:由于IdentityHashMap 使用reference-equality 进行比较,因此与使用object-equality 的HashMap 相比,查找速度更快。
- 对于比较对象实例很有用:IdentityHashMap 在您想要比较对象实例而不是对象值的情况下很有用。
使用IdentityHashMap的缺点:
- 使用更多内存:与 HashMap 相比,IdentityHashMap 使用更多内存,因为它需要存储对对象的引用。
- 不适合所有用例:IdentityHashMap 并不适合所有用例,应谨慎使用,因为它在某些情况下可能会导致意外行为。
IdentityHashMap的层次结构
它实现了可串行化,可克隆,Map接口和扩展抽象映射<K, V>类。
例子:
Java
// Java code to demonstrate IdentityHashMap
import java.util.Map;
import java.util.HashMap;
import java.util.IdentityHashMap;
public class IdentityHashMapExample
{
public static void main(String[] args)
{
// creating an instance of IdentityHashMap
Map<String, String> ihm = new IdentityHashMap<>();
// Putting key and value pair
// in a IdentityHashMap Object
ihm.put("ihmkey","ihmvalue");
ihm.put(new String("ihmkey"),"ihmvalue1");
// ihm.size() will print 2 since it
// compares the objects by reference
System.out.println("Size of IdentityHashMap--"+ihm.size());
}
}
Size of IdentityHashMap--2
IdentityHashMap 的构造函数
我们可以通过两种方式创建IdentityHashMap的实例:
IdentityHashMap<K, V> ihm = new IdentityHashMap<K, V>(); (or) Map<K, V> hm = new IdentityHashMap<K, V>();
1. IdentityHashMap():构造一个具有默认预期最大大小的新的空身份哈希映射。
IdentityHashMap<K, V> ihm = new IdentityHashMap<K, V>();
2. IdentityHashMap(int ExpectedMaxSize):构造一个具有指定预期最大大小的新的空映射。
IdentityHashMap<K, V> ihm = new IdentityHashMap(int expectedMaxSize);
3. IdentityHashMap(Map m):构造一个新的身份哈希映射,其中包含指定映射中的键值映射。
IdentityHashMap<K, V> ihm = new IdentityHashMap(Map m);
IdentityHashMap 的基本操作
1. 添加元素
要将映射插入或添加到 IdentityHashMap,我们有 put() 和 putAll() 方法。 put()可以将特定的键及其映射的值插入到特定的映射中。如果传递现有键,则先前的值将被新值替换。 putAll() 将所有元素(即映射)从一个映射复制到另一个映射。
Java
// Java code to illustrate
// adding elements to IdentityHashMap
import java.util.*;
public class AddingElementsToIdentityHashMap {
public static void main(String[] args)
{
// Creating an empty IdentityHashMap
Map<Integer, String> identity_hash
= new IdentityHashMap<Integer, String>();
// Mapping string values to int keys
// using put() method
identity_hash.put(10, "Geeks");
identity_hash.put(15, "4");
identity_hash.put(20, "Geeks");
identity_hash.put(25, "Welcomes");
identity_hash.put(30, "You");
// Displaying the IdentityHashMap
System.out.println("Initial Mappings are: "
+ identity_hash);
// Inserting existing key along with new value
// previous value gets returned and stored in
// returned_value
String returned_value
= (String)identity_hash.put(20, "All");
// Verifying the returned value
System.out.println("Returned value is: "
+ returned_value);
// Displaying the new map
System.out.println("New map is: " + identity_hash);
// Creating a new Identityhash map and copying
Map<Integer, String> new_Identityhash_map
= new IdentityHashMap<Integer, String>();
new_Identityhash_map.putAll(identity_hash);
// Displaying the final IdentityHashMap
System.out.println("The new map: "
+ new_Identityhash_map);
}
}
Initial Mappings are: {30=You, 10=Geeks, 15=4, 25=Welcomes, 20=Geeks} Returned value is: Geeks New map is: {30=You, 10=Geeks, 15=4, 25=Welcomes, 20=All} The new map: {30=You, 10=Geeks, 15=4, 25=Welcomes, 20=All}
2. 删除元素
要删除映射,我们使用IdentityHashMap remove(),IdentityHashMap 类的内置方法,用于从映射中删除任何特定键的映射。
Java
// Java code to illustrate removing
// elements from IdentityHashMap
import java.util.*;
public class RemovingMappingsFromIdentityHashMap {
public static void main(String[] args)
{
// Creating an empty IdentityHashMap
Map<Integer, String> Identity_hash = new
IdentityHashMap<Integer, String>();
// Mapping string values to int keys
Identity_hash.put(10, "Geeks");
Identity_hash.put(15, "4");
Identity_hash.put(20, "Geeks");
Identity_hash.put(25, "Welcomes");
Identity_hash.put(30, "You");
// Displaying the IdentityHashMap
System.out.println("Initial Mappings are: " +
Identity_hash);
// Removing the existing key mapping
String returned_value =
(String)Identity_hash.remove(20);
// Verifying the returned value
System.out.println("Returned value is: " +
returned_value);
// Displaying the new map
System.out.println("New map is: " + Identity_hash);
}
}
Initial Mappings are: {30=You, 10=Geeks, 15=4, 25=Welcomes, 20=Geeks} Returned value is: Geeks New map is: {30=You, 10=Geeks, 15=4, 25=Welcomes}
3. 访问元素
我们可以使用 get() 方法访问 IdentityHashMap 的元素,下面给出了示例。
Java
// Java code to illustrate the accessing
// elements from IdentityHashMap
import java.util.*;
public class AccessingElementsFromIdentityHashMap {
public static void main(String[] args)
{
// Creating an empty IdentityHashMap
Map<Integer, String> identity_hash
= new IdentityHashMap<Integer, String>();
// Mapping string values to int keys
identity_hash.put(10, "Geeks");
identity_hash.put(15, "4");
identity_hash.put(20, "Geeks");
identity_hash.put(25, "Welcomes");
identity_hash.put(30, "You");
// Displaying the IdentityHashMap
System.out.println("Initial Mappings are: "
+ identity_hash);
// Getting the value of 25
System.out.println("The Value is: "
+ identity_hash.get(25));
// Getting the value of 10
System.out.println("The Value is: "
+ identity_hash.get(10));
// Using keySet() to get the set view of keys
System.out.println("The set is: " + identity_hash.keySet());
// Using entrySet() to get the set view
System.out.println("The set is: " +
identity_hash.entrySet());
}
}
Initial Mappings are: {30=You, 10=Geeks, 15=4, 25=Welcomes, 20=Geeks} The Value is: Welcomes The Value is: Geeks The set is: [30, 10, 15, 25, 20] The set is: [30=You, 10=Geeks, 15=4, 25=Welcomes, 20=Geeks]
4. 遍历
我们可以使用 Iterator 接口来遍历 Collection Framework 的任何结构。由于迭代器使用一种类型的数据,因此我们使用 Entry< ? , ? > 将两种不同的类型解析为兼容的格式。然后使用 next() 方法打印 IdentityHashMap 的元素。
Java
// Java code to illustrate the
// iterating over IdentityHashmap
import java.util.*;
public class IteratingIdentityHashMap {
public static void main(String[] args)
{
// Creating an empty IdentityHashMap
IdentityHashMap<Integer, String> identity_hash
= new IdentityHashMap<Integer, String>();
// Mapping string values to int keys
identity_hash.put(10, "Geeks");
identity_hash.put(15, "4");
identity_hash.put(20, "Geeks");
identity_hash.put(25, "Welcomes");
identity_hash.put(30, "You");
// Displaying the IdentityHashMap
System.out.println("Initial Mappings are: "
+ identity_hash);
// Create an Iterator over the
// IdentityHashMap
Iterator<IdentityHashMap.Entry<Integer, String> >
itr = identity_hash.entrySet().iterator();
// The hasNext() method is used to check if there is
// a next element The next() method is used to
// retrieve the next element
while (itr.hasNext()) {
IdentityHashMap.Entry<Integer, String> entry
= itr.next();
System.out.println("Key = " + entry.getKey()
+ ", Value = "
+ entry.getValue());
}
}
}
Initial Mappings are: {30=You, 10=Geeks, 15=4, 25=Welcomes, 20=Geeks} Key = 30, Value = You Key = 10, Value = Geeks Key = 15, Value = 4 Key = 25, Value = Welcomes Key = 20, Value = Geeks
已同步IdentityHashMap
如果多个线程同时访问一个身份哈希映射,并且至少有一个线程在结构上修改了该映射,则必须进行外部同步。 (结构修改是添加或删除一个或多个映射的任何操作;仅更改与实例已包含的键关联的值不是结构修改。)这通常是通过在自然封装映射的某个对象上进行同步来完成的。如果不存在这样的对象,则使用Collections.synchronizedMap方法映射应该是“wrapped”。最好在创建时完成此操作,以防止意外地不同步访问Map。
Map m = Collections.synchronizedMap(new IdentityHashMap(…));
IdentityHashMap的方法
- K- Map中按键的类型。
- V- 映射中映射的值的类型。
METHOD |
DESCRIPTION |
---|---|
IdentityHashMap clear() | 从此Map中删除所有映射。 |
IdentityHashMap clone() | 返回此身份哈希映射的浅拷贝:键和值本身不会被克隆。 |
IdentityHashMap containsKey() | 测试指定的对象引用是否是此身份哈希映射中的键。 |
IdentityHashMap containsValue() | 测试指定的对象引用是否是此身份哈希映射中的值。 |
IdentityHashMap entrySet() | 返回此映射中包含的映射的 Set 视图。 |
IdentityHashMap equals() | 比较指定对象与此映射是否相等。 |
IdentityHashMap get() | 返回指定键映射到的值,如果此映射不包含该键的映射,则返回 null。 |
IdentityHashMap hashCode() | 返回此映射的哈希代码值。 |
IdentityHashMap isEmpty() | 如果此身份哈希映射不包含键值映射,则返回 true。 |
IdentityHashMap keySet() | 返回此映射中包含的键的基于身份的集合视图。 |
IdentityHashMap put() | 将指定值与此身份哈希映射中的指定键相关联。 |
IdentityHashMap putAll() | 将指定映射中的所有映射复制到此映射。 |
IdentityHashMap remove() | 从此映射中删除此键的映射(如果存在)。 |
IdentityHashMap size() | 返回此身份哈希映射中键值映射的数量。 |
IdentityHashMap values() | 返回此映射中包含的值的集合视图。 |
类 java.util.AbstractMap 中声明的方法
METHOD |
DESCRIPTION |
---|---|
toString() | 返回此Map的字符串表示形式。 |
接口 java.util.Map 中声明的方法
METHOD |
DESCRIPTION |
---|---|
计算?(K key, BiFunction<? super K,?? super V,?? extends V> remappingFunction) | 尝试计算指定键及其当前映射值的映射(如果没有当前映射,则为 null)。 |
computeIfAbsent?(K key, Function<? super K,?? 扩展 V> 映射函数) | 如果指定的键尚未与值关联(或映射为 null),则尝试使用给定的映射函数计算其值并将其输入到此映射中,除非 null。 |
computeIfPresent?(K key, BiFunction<? super K,?? super V,?? extends V> remappingFunction) | 如果指定键的值存在且非空,则尝试在给定键及其当前映射值的情况下计算新映射。 |
forEach?(BiConsumer<?超级K,??超级V>动作) | 对此映射中的每个条目执行给定的操作,直到处理完所有条目或该操作引发异常。 |
getOrDefault?(对象键,V defaultValue) | 返回指定键映射到的值,如果此映射不包含该键的映射,则返回 defaultValue。 |
合并?(K key, V value, BiFunction<? super V,?? super V,?? extends V> remappingFunction) | 如果指定的键尚未与值关联或与 null 关联,则将其与给定的非 null 值关联。 |
putIfAbsent?(K 键,V 值) | 如果指定的键尚未与值关联(或映射为 null),则将其与给定值关联并返回 null,否则返回当前值。 |
删除?(对象键,对象值) | 仅当指定键当前映射到指定值时,才删除该条目。 |
替换?(K键,V值) | 仅当指定键当前映射到某个值时才替换该条目。 |
替换?(K 键,V 旧值,V 新值) | 仅当当前映射到指定值时才替换指定键的条目。 |
ReplaceAll?(BiFunction<? super K,?? super V,?? extends V> 函数) | 将每个条目的值替换为在该条目上调用给定函数的结果,直到处理完所有条目或函数引发异常。 |
IdentityHashMap vsHashMap
- IdentityHashMap 使用相等运算符 “==” 来比较键和值,而 HashMap 使用 equals 方法来比较 Map 中的键和值。
- 由于 IdentityHashMap 不使用 equals(),因此对于具有昂贵的 equals() 的对象来说,它比 HashMap 更快。
- IdentityHashMap 不要求 key 不可变,因为它不依赖于 equals()。
以下示例程序旨在说明 IdentityHashMap 和 HashMap 实现之间的差异。
Java
// Java code to demonstrate IdentityHashMap and
// illustration of how it is different from HashMap
import java.util.Map;
import java.util.HashMap;
import java.util.IdentityHashMap;
public class IdentityHashMapExample
{
public static void main(String[] args)
{
// Creating HashMap and IdentityHashMap objects
Map<String, String> hm = new HashMap<>();
Map<String, String> ihm = new IdentityHashMap<>();
// Putting key and value in HashMap and IdentityHashMap Object
hm.put("hmkey","hmvalue");
hm.put(new String("hmkey"),"hmvalue1");
ihm.put("ihmkey","ihmvalue");
ihm.put(new String("ihmkey"),"ihmvalue1");
// Print Size of HashMap and WeakHashMap Object
// hm.size() will print 1 since it compares the objects logically
// and both the keys are same
System.out.println("Size of HashMap is : "+hm.size());
// ihm.size() will print 2 since it compares the objects by reference
System.out.println("Size of IdentityHashMap is : "+ihm.size());
}
}
Size of HashMap is : 1 Size of IdentityHashMap is : 2
IdentityHashMap是Java中的一个类,它实现了Map接口并使用引用相等来比较键。它与常规 HashMap 类似,但它使用 == 运算符来比较键,而不是 equals() 方法。这意味着具有相同内容但不同对象引用的两个键将被视为 IdentityHashMap 中不同的键。
以下是如何在 Java 中使用 IdentityHashMap 的示例:
Java
import java.util.IdentityHashMap;
public class IdentityHashMapExample {
public static void main(String[] args) {
IdentityHashMap<String, Integer> map = new IdentityHashMap<>();
// Add key-value pairs to the map
String key1 = new String("key");
String key2 = new String("key");
map.put(key1, 1);
map.put(key2, 2);
// Get values from the map using the same and different keys
System.out.println(map.get(key1)); // Output: 1
System.out.println(map.get(key2)); // Output: 2
System.out.println(map.get(new String("key"))); // Output: null
}
}
1 2 null
在此示例中,我们创建一个 IdentityHashMap 将字符串键映射到整数值。我们使用两个具有相同内容的不同 String 对象将两个键值对添加到映射中。然后,我们使用相同和不同的 String 对象从映射中检索值。我们发现可以使用具有相同内容的两个不同键从映射中检索值,但无法使用具有相同内容但不同对象引用的 String 对象检索值。
请注意,IdentityHashMap 的行为与常规 HashMap 略有不同,并且通常仅在引用相等很重要的某些情况下有用。在大多数情况下,常规的 HashMap 就足够并且更合适。
相关用法
- Java IdentityHashMap clear()用法及代码示例
- Java IdentityHashMap clone()用法及代码示例
- Java IdentityHashMap containsKey()用法及代码示例
- Java IdentityHashMap containsValue()用法及代码示例
- Java IdentityHashMap entrySet()用法及代码示例
- Java IdentityHashMap equals()用法及代码示例
- Java IdentityHashMap get()用法及代码示例
- Java IdentityHashMap hashCode()用法及代码示例
- Java IdentityHashMap isEmpty()用法及代码示例
- Java IdentityHashMap keySet()用法及代码示例
- Java IdentityHashMap put()用法及代码示例
- Java IdentityHashMap putAll()用法及代码示例
- Java IdentityHashMap remove()用法及代码示例
- Java IdentityHashMap size()用法及代码示例
- Java IdentityHashMap values()用法及代码示例
- Java Integer divideUnsigned()用法及代码示例
- Java Integer equals()用法及代码示例
- Java Integer getInteger()用法及代码示例
- Java Integer longValue()用法及代码示例
- Java Integer max()用法及代码示例
- Java Integer min()用法及代码示例
- Java Integer numberOfLeadingZeros()用法及代码示例
- Java Integer numberOfTrailingZeros()用法及代码示例
- Java Integer parseInt()用法及代码示例
- Java Integer parseUnsignedInt()用法及代码示例
注:本文由纯净天空筛选整理自佚名大神的英文原创作品 IdentityHashMap class in Java。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。