HashMap
底层: 哈希表存储(数组+链表+红黑树)
特点: 查询,增删效率高,但是无序,存储键值对的值
去重: 根据key做去重,根据key计算桶的位置
扩容:
初始容量: 默认初始用量为16
加载因子: 0.75 当16*0.75达到一个临界点12进行扩容
扩容: 每次扩容原大小的2倍
总结:
如果存储键值对数据–>Map,HashMap
如果存储的单个数据值–>Collection
如果有序,可重复,根据根据索引进行操作 List
大量操作查询 : ArrayList
大量增删操作: LinkedList
如果无序,去重–>Set
HashSet
HashSet–>底层就是用HashMap维护的的key
TreeSet–>底层是由TreeMap维护的key
TreeMap: Map的实现类
底层: 红黑树
特点: 默认升序存储数据
注意: 去重排序都是根据兼职对的key进行计算
import java.util.HashSet;
import java.util.TreeSet;
public class HashMap02 {
public static void main(String[] args) {
TreeSet t = new TreeSet();
t.add("abc");
t.add("ab");
t.add("ba");
t.add("b");
t.add("a");
System.out.println(t);
}
}
简单的HashMap
public class Node {
int hash; //桶的位置
Object key;
Object value;
Node next; //下个节点的地址
}
public class MyHashMap03 {
public static void main(String[] args) {
MyHashMap my = new MyHashMap();
my.put(10,"aa");
my.put(20,"bb");
System.out.println(my.size);
}
}
class MyHashMap{
Node[] table; //位桶数组
int size; //存储数据的个数
public MyHashMap() {
table = new Node[16];
}
public void put(Object key,Object value) {
//1.获取key的hashcode()值,经过hash算法,计算桶的位置
int hash = hash(key.hashCode(),table.length);
//新节点
Node newNode = new Node();
newNode.hash=hash;
newNode.key=key;
newNode.value=value;
newNode.next=null;
//根据已经计算出桶的位置找到
Node node = table[hash];
//如果桶中没有节点数据,newNode节点,作为第一个节点链表头存在,直接放入
if(node==null) {
table[hash] = newNode;
size++;
}else {
while(true) {
//如果key相等,value覆盖
if(node.key.equals(key)) {
node.value = value;
break;
}
//判断是存在下一个节点
if(node.next==null) {
node.next = newNode;
size++;
break;
}
node = node.next;
}
}
}
public int size() {
return this.size;
}
/**
* 根据key的hashcode码计算hash值
* @param hashcode key的
* @param length 数组的长度
* @return 桶的位置
*/
public int hash(int hashcode,int length) {
return hashcode & (length-1);
}
}
使用HashMap 和 TreeMap分别存储数据,key为Person类型,value任意类型都可以,进行测试,达到如果Person成员属性都相同,就为一个对象,实现去重
如果TreeMap的排序,要求根据年龄进行升序排序 HashMap的key存储自定义引用数据类型: 需要重写equals和hashcode方法 TreeMap的key存储为自定义引用数据类型: 需要实现内部|外部比较器public class MapTest04 {
public static void main(String[] args) {
//Map map = new HashMap();
Map map = new TreeMap((p1,p2)-> ((Person)p1).getAge()-((Person)p2).getAge());
map.put(new Person("张三",18),"男");
map.put(new Person("王五",17),"女");
map.put(new Person("李四",19),"女");
//根据key做去重,
map.put(new Person("李四",19),"男");
System.out.println(map);
}
}
public class MyHashMap03 {
public static void main(String[] args) {
MyHashMap my = new MyHashMap();
my.put(10,"aa");
my.put(20,"bb");
my.put(30,"cc");
System.out.println(my.size);
System.out.println(my.get(10));
System.out.println(my.get(20));
System.out.println(my);
}
}
class MyHashMap{
Node[] table; //位桶数组
int size; //存储数据的个数
public MyHashMap() {
table = new Node[16];
}
//获取 根据key获取value
public Object get(Object key) {
//桶的位置
int hash = hash(key.hashCode(),table.length);
Node node = table[hash];
while(node!=null) {
if(node.key.equals(key)) {
return node.value;
}
node = node.next; //node永远指向新节点
}
return null;
}
//添加
public void put(Object key,Object value) {
//1.获取key的hashcode()值,经过hash算法,计算桶的位置
int hash = hash(key.hashCode(),table.length);
//新节点
Node newNode = new Node();
newNode.hash=hash;
newNode.key=key;
newNode.value=value;
newNode.next=null;
//根据已经计算出桶的位置找到
Node node = table[hash];
//如果桶中没有节点数据,newNode节点,作为第一个节点链表头存在,直接放入
if(node==null) {
table[hash] = newNode;
size++;
}else {
while(true) {
//如果key相等,value覆盖
if(node.key.equals(key)) {
node.value = value;
break;
}
//判断是存在下一个节点
if(node.next==null) {
node.next = newNode;
size++;
break;
}
node = node.next;
}
}
}
public int size() {
return this.size;
}
/**
* 根据key的hashcode码计算hash值
* @param hashcode key的
* @param length 数组的长度
* @return 桶的位置
*/
public int hash(int hashcode,int length) {
return hashcode & (length-1);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("[");
//循环遍历数组table
for(Node node:table) {
// 遍历的是每一个位桶中的链表
while(node!=null) {
sb.append(node.key+"="+node.value+",");
node = node.next;
}
}
return sb.toString().substring(0,sb.length()-1)+"]";
}
}