文章目录
1.Map的实现类的结构
Map: 双列数据,存储key-value对的数据。
- HashMap: 作为Map的主要实现类;线程不安全的,效率高;可以存储null的key和value.
》LinkedHashMap: 保证在遍历map元素时,可以按照添加的顺序实现遍历. 原因:在原有的HashMap底层基础上,添加了一对指针,指向前一个和后一个元素. 对于频繁的遍历操作,此类执行效率高于HashMap.- TreeMap: 保证按照添加的key-value对进行排序,实现排序遍历.此时考虑key的自然排序或定制排序。底层使用红黑树。
- Hashtable: 作为古老的实现类;线程安全的,效率低;不能存储null的key和value.
》Properties: 常用来处理配置文件. key和value都是String类型.- HashMap的底层:
》数组+链表(jdk7及之前)
》数组+链表+红黑树(jdk8)
- Map结构的理解
- Map中的key:无序的、不看重复的,使用Set存储所有的key —->key所在类要重写equals()和hashCode().
- Map中的value:无序的、可重复的,使用Collection存储所有的value, —>value所在类要重写equals().
- 一个键值对:key-value构成了一个Entry对象。
- Map中的entry:无序、不可重复的、使用Set存储所有的entry。
2.HashMap的底层实现原理(以JDK7为说明)
HashMap map=new HashMap(); //在实例化以后,底层创建了长度为16的一维数组Entry[] table。
-----可能已经执行过多次put()------
map.put(key1,value1):
首先,调用key1所在类的hashCode()计算key1哈希值,此哈希值经过某种算法计算以后,得到Entry数组中的存放位置。
- 如果此位置上的数据为空,此时key1-value1添加成功。 ----情况1
- 如果此位置上的数据不为空,(意味着此位置上存在一个或多个数据(以链表形式存在)),
比较key1和已经存在的一个或多个数据的哈希值:
--如果key1的哈希值与已经存在的数据的哈希值不相同,此时key1-value1添加成功 ---情况2
--如果key1的哈希值和已经存在的某一个数据(key2-value2)的哈希值相同,
继续比较:调用key1所在类的equals(keys):
---如果equals返回false:此时key1-value1添加成功。 ---情况3
---如果equals返回true:使用value1替换value2。
-补充:关于情况2和情况3:此时key1-value1和原来的数据以链表的方式存储。
-在不断的添加过程中,会涉及到扩容问题,当超出临界值(且要存放的位置非空),扩容。默认的扩容方式:扩容为原来容量的2倍,并将原有数据复制过来。
- JDK8相较于JDK7在底层实现方面的不同:
1.new HashMap():底层没有创建一个长度为16的数组
2.JDK8底层的数组是:Node[],而非Entry[]
3.首次调用put()方法时,底层创建长度为16的数组。
4.JDK7底层结构只有:数组+链表。JDK8中底层结构:数组+链表+红黑树。
当数组的某一个索引位置上的元素以链表形式存在的数据个数 >8 且当前数组的长度 >64时,
此时此索引位置上的所有数据改为使用红黑树存储。
3.LinkedHashMap的底层实现原理
源码中:
static class Entry<K,V> extends HashMap.Node<K,V>{
Entry<K,V> before,after; //能够记录添加的元素的先后顺序
Entry(int hash,K key,V value,Node<K,V> next){
super(hash,key,value,next);
}
}
4.Map接口:常用方法
- 添加、删除、修改操作:
》Object put(Object key,Object value): 将指定key-value添加到(或修改)当前map对象中。
》void putAll(Map m): 将m中的所有key-value存放到当前map中。
》Object remove(Object key): 移除指定的key的key-value对,并返回value。
》void clear(): 清空当前map中的所有数据。- 元素查询的操作:
》Object get(Object key): 获取指定key对应的value.
》boolean containsKey(Object key): 是否包含指定的key.
》boolean containsValue(Object value): 是否包含指定的value。
》int size(): 返回map中key-value对的个数。
》boolean isEmpty(): 判断当前map是否为空。
》boolean equals(Object obj): 判断当前map和参数对象obj是否相等。- 元视图操作的方法:
》Set keySet(): 返回所有key构成的Set集合。
》Collection values(): 返回所有value构成的Collection集合。
》Set entrySet(): 返回所有key-value对构成的Set集合。
- 遍历HashMap集合
Map map=new HashMap();
map.put("AA",123);
map.put(45,1234);
map.put("BB",56);
//遍历所有的key集:keySet()
Set set=map.keySet();
Iterator iterator=set.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
//遍历所有的value集:values()
Collection values=map.values();
for(Object obj:values){
System.out.println(obj);
}
//遍历所有的key-value
//方式一:entrySet():
Set entrySet=map.entrySet();
Iterator iterator1=entrySet.iterator();
while(iterator1.hasNext()){
Object obj=iterator1.next();
Map.Entry entry=(Map.Entry) obj;
System.out.println(entry.getKey()+"-->"+entry.getValue());
}
//方法二:
Set keySet=map.KeySet();
Iterator iterator2=keySet.iterator();
while(iterator2.hasNext()){
Object key=iterator2.next();
Ojbect value=map.get(key);
System.out.println(key+"===="+value);
}
5.TreeMap
- 自然排序
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class TreeMapTest {
//向TreeMap中添加key-value,要求key必须是由同一个类创建的对象。
//因为是要按照key进行排序:自然排序,定制排序
public static void main(String[] args) {
//自然排序
TreeMap map=new TreeMap();
Person p1=new Person("Tom",18);
Person p2=new Person("Jerry",20);
Person p3=new Person("Jack",19);
Person p4=new Person("Rose",24);
map.put(p1,98);
map.put(p2,89);
map.put(p3,76);
map.put(p4,100);
Set entrySet=map.entrySet();
Iterator iterator=entrySet.iterator();
while(iterator.hasNext()){
Object obj=iterator.next();
Map.Entry entry=(Map.Entry)obj;
System.out.println(entry.getKey()+"---->"+entry.getValue());
}
}
}
import java.util.Objects;
public class Person implements Comparable {
private String name;
private int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
System.out.println("Person equals....");
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
//按照姓名从小到大排列
@Override
public int compareTo(Object o) {
//如果是Person
if (o instanceof Person){
Person person=(Person) o;
//按照姓名从小到大排列:return this.name.compareTo(person.name);
//按照姓名从大到小排列: return -this.name.compareTo(person.name);
int compare=this.name.compareTo(person.name);
if(compare!=0){
return compare;
}else{
return Integer.compare(this.age,person.age);
}
}else{
throw new RuntimeException("输入的类型不匹配!");
}
}
}
- 定制排序
import java.util.*;
public class TreeMapTest {
//向TreeMap中添加key-value,要求key必须是由同一个类创建的对象。
//因为是要按照key进行排序:自然排序,定制排序
public static void main(String[] args) {
//定制排序:年龄从小到大
TreeMap map=new TreeMap(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
if (o1 instanceof Person && o2 instanceof Person) {
Person p1 = (Person) o1;
Person p2 = (Person) o2;
return Integer.compare(p1.getAge(), p2.getAge());
}
throw new RuntimeException("输入的类型不匹配!!");
}
});
Person p1=new Person("Tom",18);
Person p2=new Person("Jerry",20);
Person p3=new Person("Jack",19);
Person p4=new Person("Rose",24);
map.put(p1,98);
map.put(p2,89);
map.put(p3,76);
map.put(p4,100);
Set entrySet=map.entrySet();
Iterator iterator=entrySet.iterator();
while(iterator.hasNext()){
Object obj=iterator.next();
Map.Entry entry=(Map.Entry)obj;
System.out.println(entry.getKey()+"---->"+entry.getValue());
}
}
}
6.Properties
- Properties类是Hashtable的子类,对该对象用于处理属性文件。
- 由于属性文件里的key、value都是字符串类型,所以Properties里的key和value都是字符串类型。
- 存取数据时,建议使用setProperty(String key,String value)方法和getProperty(String key)方法。
Properties pros=new Properties();
pros.load(new FileInputStream("jdbc.properties"));
String user=pros.getProperty("user");
System.out.println(user);
版权声明:本文为RufyHuang原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。