一、HashMap、HashSet认识
二、HashMap、HashTable认识
三、HashMap、HashSet的基本使用
四、HashTable的用法
五、“Usage of API documented as @since 1.8+”报错的解决办法
HashMap、HashSet认识
- HashSet实现了set接口,它不允许集合中有重复的值,当我们提到HashSet时,第一件事情就是在将随想存储在HashSet之前,要先确保对象重写equals()和hashCode()方法,这样才能比较对象的值是否相等,以确保set中没有储存相等的对象。如果我们没有重写这两个方法,将会使用这个方法的默认实现。public boolean add(Object o) 方法用来在Set中添加元素,当元素重复时则会立即返回false,如果添加成功会返回true。
- HashMap实现了Map接口,Map接口对键值进行映射。Map中不允许重复的键,Map接口有两个基本的实现,HashMap和TreeMap。Tree Map保存了对象的排列次序,而HashMap则不能。Hash Map运行键和值为NULL,HashMap是非synchronized的,但collection框架提供方法保证Hash Map synchronized,这样多个线程同时访问HashMap时,能保证只有一个线程更改Map.
- public Objecct put(Object key,Object value)方法用来将元素添加到map中。
HashMap和HashSet的区别:
HashMap | HashSet |
---|---|
HashMap实现了Map接口 | Hash Set实现了Set接口 |
Hash Map存储的时键值对 | HashMap仅仅存储对象 |
使用put方法将元素放入map中 | 使用add()方法将元素放入set中 |
HashMap中使用键对象来计算HashCode值 | HashSet使用成员对象来计算hashcode的值,对于两个对象来说hashcode可能相同,所以equals()方法用来判断对象的相等性,如果两个对象不同的话,那么返回false |
HashMap比较快,因为是使用唯一的键来获取对象 | HashSet较HashMap慢一些 |
HashMap、HashTable认识
HashMap基于hashing原理,我们通过put()和get()方法储存和获取对下个。当我们将键值对传递给put()方法时,它调用键对象的hashCode()方法来计算hashcode,然后找到bucket位置来储存值对象。当你获取对象时,通过键对象的equals方法找到正确的键值时,然后返回值对象。HashMap使用链表来解决碰撞问题,当碰撞发生了,对象会储存在链表的下一个节点中。HashMap在每个链表节点中储存键值对对象。
HashMap和HashTable都实现了Map接口,主要的区别:线程安全性,同步(synchronization),以及速度。
- HashMap除了是非synchronized的,并可以接受null的键和值,几乎等价于HashTable
- HashMap是非synchronized,而HashTable是synchronized,这意味着Hash Table是线程安全的,多个线程可以共享一个HashTable;而如果没有正确同步的话,多个线程是不能共享HashMap的。java5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。
- 另一个区别是HashMap的迭代器(iterator)是fail-fast迭代器,而hashTable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。这条同样也是Enumeration和iterator的区别。
- 由于HashTable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好过Hashtable。
- HashMap不能保证随着时间的推移Map中的元素次序是不变的
HashMap | HashTable |
---|---|
线程不安全 | 线程安全 |
允许有null的键和值 | 不允许有null的键和值 |
效率高一点 | 效率稍低 |
方法不是Synchronize的要提供对外同步 | 方法是Synchronize的 |
有containsvalue和containsKey方法 | 有contains方法 |
HashMap是Java1.2引进的Map interface的一个实现 | HashTable继承于Dictionary类 |
HashMap是Hashtable的轻量级实现 | HashTable比HashMap要旧 |
HashMap、HashSet的基本使用
package JavaSEWY;
import java.util.HashMap;
import java.util.HashSet;
public class hello {
public static void main(String[] args) {
HashSet<Integer> hashset = new HashSet<>();
hashset.add(0);
hashset.add(1);
hashset.add(1);
hashset.add(2);
//查看hashset的长度
System.out.println("hashset的长度: " + hashset.size());
//遍历HashSet中的元素
for (Integer integer: hashset)
{
System.out.println("2 HashSet中的元素如下:" +integer);
}
//查看hashSet中是否包含0,返回值为True or False
System.out.println("HashSet中是否包含4,返回值为:" + hashset.contains(4));
System.out.println("----我是分割线----");
HashMap<Integer, Integer> hashmap = new HashMap<>();
hashmap.put(1,2);
hashmap.put(3,4);
hashmap.put(5,6);
//替换key=2时,value的值更换为4;成功与否的返回值都是True或者False
System.out.println("replace是否成功替换value的值,返回值为:" + hashmap.replace(2,1,4));
System.out.println("-------------------");
//首先查找key,找到了返回key对应的value;找不到返回null
System.out.println("返回key对应的value"+ hashmap.get(3));
System.out.println("-------------------");
System.out.println("HashMap中key的集合:" + hashmap.keySet());
System.out.println("-------------------");
System.out.println("HashMap中value的集合:" +hashmap.values());
System.out.println("-------------------");
System.out.println("输出HashMap中key=value的集合:"+hashmap.entrySet());
}
}
运行结果:
hashset的长度: 3
2 HashSet中的元素如下:0
2 HashSet中的元素如下:1
2 HashSet中的元素如下:2
HashSet中是否包含4,返回值为:false
----我是分割线----
replace是否成功替换value的值,返回值为:false
-------------------
返回key对应的value4
-------------------
HashMap中key的集合:[1, 3, 5]
-------------------
HashMap中value的集合:[2, 4, 6]
-------------------
输出HashMap中key=value的集合:[1=2, 3=4, 5=6]
可以自行去HashMap和HashSet中查看对应源码:
- hashmap.get(3) ==>定位到源码:
public V get(Object key) {
Node<K,V> e;
return (e = getNode(hash(key), key)) == null ? null : e.value;
}
源码中的解释:
/**
* Returns the value to which the specified key is mapped,
* or {@code null} if this map contains no mapping for the key.
*
* <p>More formally, if this map contains a mapping from a key
* {@code k} to a value {@code v} such that {@code (key==null ? k==null :
* key.equals(k))}, then this method returns {@code v}; otherwise
* it returns {@code null}. (There can be at most one such mapping.)
*
* <p>A return value of {@code null} does not <i>necessarily</i>
* indicate that the map contains no mapping for the key; it's also
* possible that the map explicitly maps the key to {@code null}.
* The {@link #containsKey containsKey} operation may be used to
* distinguish these two cases.
*
* @see #put(Object, Object)
*/
翻译:返回指定键映射到的值
1)、如果此映射不包含键的映射,返回值是null
2)、如果此映射包含一个key,eg: hashmap.put(3,4); 我们使用hashmap.get(3) ==>
取到对应的value值是4;hashmap.get(4) ==> key找不到对应的value,返回值就是null
英语课:explicitly:明确的 distinguish:区分、辨别
Hashtable的用法
需求:把姓名-年龄这样的信息存入一个容器,将来查A多少岁,立刻能出来年龄?
package day0720;
import java.util.Enumeration;
import java.util.Hashtable;
public class HashTableApp {
public static void main(String[] args) {
Hashtable hashtable = new Hashtable();
hashtable.put("one", new Integer(1));
hashtable.put("two", new Integer(2));
hashtable.put("three", new Integer(3));
hashtable.put("four", new Integer(4));
Integer hashtable1 = (Integer) hashtable.get("twotwo");
if (hashtable1 != null) {
System.out.println("won't print = " + hashtable1);
}
Integer m = (Integer) hashtable.get("two");
if (m != null) {
System.out.println("two:" + m);
}
Enumeration e = hashtable.elements();
while (e.hasMoreElements()) {
System.out.println(e.nextElement());
}
Enumeration ke = hashtable.keys();
while (ke.hasMoreElements()) {
System.out.println(ke.nextElement());
}
}
输出:
two:2
2
1
3
4
two
one
three
four
“Usage of API documented as @since 1.8+”报错的解决办法
报错信息:
Usage of API documented as @since 1.8+
This inspection finds all usages of methods that have @since tag in their documentation.
This may be useful when development is performed under newer SDK version as the target platform for production.
解决: ctrl+shift+alt+S,修改Language Level为8