Set接口:
Set的底层就是Map
特点:
1.没有索引值(因为哈希表底层是java.util.HashMap$Node这个类型的数组,Node是一个链表结构,一个索引值下可能有多个元素)
2.不能重复
例:添加了两个相同元素,但只新增了一个元素
常用实现类:
HashSet:无序:新增顺序和取出顺序不一定一致,先增加的元素算出来的索引值位置可能靠后,后增的元素算出来的索引值位置可能靠前,去获取索引值时,是从索引值0开始依次去获取的
例:
构造方法:
public HashSet();
public HashSet(int capacity);
public HashSet(int capacity,float loadFactor);
底层数据结构:哈希表(数组+链表/红黑)
数组:查询快,增删慢 链表:查询慢,增删快 所以哈希表查询和增删都快。
什么类型的数组:java.util.HashMap$Node(表示一个单项链表)
数组长度是多少:16
如何判断新增的两个元素是否重复:
比较两个对象的哈希值 && (地址值相同 || equals相同)
新增过程:
a.计算新增元素的哈希值
b.(假设数组已经创建出来),通过 hash%数组长度
c.如果该位置为null:则直接新增
如果该位置不为null:
c1.判断该元素是否重复:
c11.如果不重复,则新增到该索引值位置链表的最后面
c12.如果重复:则不新增
例:定义一个Person类(包含name和age两个变量),创建两个对象存入集合,我们希望同名同age就是一个人,如果直接写则会新增两个元素,所以需要我们根据新增规则重写方法。分析:如何判断新增的两个元素是否重复:比较两个对象的哈希值 && (地址值相同 || equals相同)
改前:
改后:
什么情况下链表会转红黑树:
当同一索引值下元素个数>8,并且数组长度>=64(会把该索引值下的元素转换为红黑树)
什么情况下会扩容:
a.当同一索引值下元素个数>8,并且数组长度<64
b.数组的索引值,占有>到0.75,会扩容
注意:同一索引值下元素不能超过8个,如果超过:
1.扩容,把元素分开,让其小于8个
2.把链表结构转换成红黑树
新容量 = 旧容量<<1;
可以通过构造方法指定加载因子。
可以通过构造方法指定哈希表数组的长度:
实际的长度>=传入容量,则最近2的次方的值。
LinkedHashSet:有序
构造方法:
public LinkedHashSet();
底层数据结构:链表+哈希表
Map<K,V>接口:
特点:
1.一个元素由K,V两个部分组成
2.K,V可以是任意的引用数据类型
3.K不能重复
常用方法:
//如果K不存在,返回null
//如果K存在,返回被替换的V
V put(K k,V v);
//根据K获取对应的V
V get(Object key);
//根据K删除整个键值对(元素)
V remove(Object key);
//是否包含Key
boolean containsKey(Object key);
boolean containsValue(Object value);
boolean isEmpty();
void clear();
int size();
Set<K> keySet();
Collection<V> values();
Set<Entry<K,V>> entrySet();
实现类:
HashMap:无序。底层的数据结构是哈希表
构造方法:
public HashMap();
Hashtable:功能和HashMap一致(HashMap可以有null值和null键, Hashtable不能有null) Hashtable线程安全,效率低;HashMap线程不安全,效率高
LinkedHashMap:有序。底层的数据结构是链表+哈希表
构造方法:
public LinkedHashMap();
TreeMap:可排序。底层的数据结构是红黑树 。只能通过K来排序
构造方法:
public TreeMap();
Entry<K,V>接口:
K getKey();
V getValue();
例:定义一个Person类(包含name和age两个变量),创建四个对象存入集合,我们希望同名同age就是一个人,如果直接写则会新增四个元素,所以需要我们根据新增规则重写方法。分析:如何判断新增的两个元素是否重复:比较两个对象的哈希值 && (地址值相同 || equals相同)
改前:
改后: