博主之前学习了map的接口以及底层实现原理,但是后面又忘记,用的时候比较困惑,所以回来重新整理,涵盖了Map基础,未整理hashmap线程不安全,分段锁这一块。
1.常用的实现类结构
Map:双列数据 存储使用key—value对的数据 类似y = f(x)
----hashMap:主要实现类 线程不安全 效率高 可以存储null的key和value
----LinkHashMap:可以按照添加顺序实现遍历
原因:在底层结构基础上,添加了一对指针,指向前一个后一个元素,如果频繁的遍历,推荐使用。
----SortedMap
----TreeMap:对key实现了自然排序或者定制排序
----Hashtable:最老的实现类,线程安全,效率底,不能存储null的key和value
----properties:常用来处理配置文件,String:key value
【面试题】、
1.hashmap和hashtable的异同
答:效率线程安全、keyvalue能否null、子类的功能
2.Map的存储结构
key:使用set存储 无序的不可重复的 -->所在类需要重写hashcode和qeuals
value:使用collection存储 无序 可重复 -->所在类重写equals方法
Map中的entry:<key,value>是一个entry(键值对) 使用set存储
3.HashMap内存结构说明
#### 3.1 jdk1.7
HashMap map = new HashMap();
map.put(key1,value1)
....
map.put(keyn,valuen)
实例化之后,底层创建长度16一维数组Entry[] table;执行put时,首先通过key所在类的hashcode()得hash值,通过某种算法得到在Entry数组的存储位置,如果此位置为空,直接添加。位置不为空,比较Hash值,值不同,添加。如果值相同,调用equals,如果相同,直接覆盖value值,相当于修改,如果不同,进行添加。
注意:在数组相同位置上进行添加的时候,以链表的方式存储。添加过程中,超过临界值,数组扩大两倍
临界值的计算:初始大小*负载因子 默认16 * 0.75=12
#### 3.2 jdk1.8与jdk1.7的不同
1.new HashMap(): 未创建容量16的底层数组
2.jdk8的底层数字组的Node[]
3.调用put的时候开始创建长度是16的数组
4.1.7的底层结构是数组+链表 1.8:数组+链表+红黑树
5.形成链表时 七上八下(7:新的指向旧的 8:旧的指向新的)
6.当数组的某一个索引以链表形式存在的数据个数>8 数组的长度>64 采用红黑树
4.方法
- 添加:put(Object key,Object value)
- 删除:remove(Object key)
- 修改:put(Object key,Object value)
- 查询:get(Object key)
- 长度:size()
- 遍历:keySet() / values() / entrySet()
实现代码
准备类
public class User implements Comparable{
String name;
int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof User)) return false;
User user = (User) o;
if (getAge() != user.getAge()) return false;
return getName() != null ? getName().equals(user.getName()) : user.getName() == null;
}
@Override
public int hashCode() {
int result = getName() != null ? getName().hashCode() : 0;
result = 31 * result + getAge();
return result;
}
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;
}
public User() {
}
@Override
public int compareTo(Object o) {
if (o instanceof User){
User user = (User)o;
return Integer.compare(this.age,user.age);
}else {
throw new RuntimeException("类型不匹配");
}
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
HashTree的实现类
import org.junit.Test;
import java.util.*;
public class HashTreeTest {
//根据传入类进行自然排序(年龄小到大)
@Test
public void test1(){
TreeMap map = new TreeMap();
User u1 = new User("TOM1", 19);
User u2 = new User("TOM2", 18);
User u3 = new User("TOM3", 22);
User u4= new User("TOM4", 16);
map.put(u1,90);
map.put(u2,80);
map.put(u3,100);
map.put(u4,89);
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());
}
}
//自制排序 年龄大到小
@Test
public void test2(){
TreeMap map = new TreeMap((Object o1,Object o2)->{
User u1 = (User)o1;
User u2 = (User)o2;
return -Integer.compare(u1.getAge(),u2.getAge());
});
User u1 = new User("TOM1", 19);
User u2 = new User("TOM2", 18);
User u3 = new User("TOM3", 22);
User u4= new User("TOM4", 16);
map.put(u1,90);
map.put(u2,80);
map.put(u3,100);
map.put(u4,89);
Set entrySet = map.entrySet();
for (Object o : entrySet) {
Map.Entry entry = (Map.Entry) o;
System.out.println(entry.getKey());
}
}
}
properties实现类
import java.io.FileInputStream;
import java.io.IOException;
public class Properties {
public static void main(String[] args) {
FileInputStream fis = null;
try {
java.util.Properties pros = new java.util.Properties();
fis = new FileInputStream("jdbc.properties");
pros.load(fis);
String name = pros.getProperty("name");
String password = pros.getProperty("password");
System.out.println("name = " + name + ", password = " + password);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}