目录
注:
List 有序可重复
ArrayList : 查询快,底层是数组
LinkedList : 添加删除快,底层是双向链表
Set 无序不可重复
HashSet : 底层是散列表
TreeSet : 底层是红黑树,元素必须有序
Map 无序,key不能重复,value能重复,保存映射关系
HashMap : 底层是散列表
TreeMap : 底层是红黑树,元素必须有序
1. 散列表
1.1 概述
用于存储键值对映射关系(K - V), 存储方式为数组中保存链表, 用于解决哈希冲突问题
底层代码注解 :
1.2 HashSet
当我们使用HashSet的时候,其实就等于是再使用HashMap
添加数据的时候,虽然调用的是HashSet的add方法,但是本质还是调用map的put方法 ,(在map中,put是添加操作), 而 map中 需要保存的是k和v映射关系,所以在set中有一个变量保存了value的值, 所以我们再进行set添加的时候,只操作了map中的key,value值我们不再关心
HashSet在数据较少的时候用数组中保存单链表的形式存储, 当数据足够多的时候用数组中保存红黑树(二分法)形式存储
TREEIFY_THRESHOLD默认值是8 , 链表元素个数达到8个,数组长度大于等于64,需要使用红黑树
使用同TreeSet 一样
2. Map
2.1 概述
当k重复时, 后输入的K-V键值会覆盖之前的K-V键值
散列表 : 用于存储键值对映射关系(K-V) , 存储方式为数组中保存链表,用于解决哈希冲突问题
java中 散列表 对应的就是 HashMap, 但是1.8开始,为了提高查询效率,引入了红黑树
想要把数据添加在散列表中,需要根据key生成hash值(java中指的hashCode方法),然后根据算法得到数组下标, 如果下标中没有对应的数据,则添加到数组中即可, 如果下标中有对应的数据,则需要调用要添加的key和对应的数据进行比较(equals),如果发生重复,则value值替换 ,如果不重复,说明是hash冲突,则把k-v插入的对应的链表中(节点对象中,包含4个属性: hash值,key,value,next)
相同对象生成多次hash,一定是相同的值,但是不同对象也有可能生成相同的hash值,叫哈希冲突
2.2 继承体系
2.3 常用方法
Map不能直接遍历
2.4 HashMap
底层代码主要是散链表(单链表)
import java.util.HashMap;
import java.util.Map;
public class HashMap_03 {
public static void main(String[] args) {
Map map = new HashMap();
// 增 , key不可重复,如果key重复,则value值替换
map.put("a", 1);
map.put("A", 2);
map.put('A', 3);
map.put(65, 4);
map.put('A', 5);
// 删
map.remove(65);
// 改,key不能修改,只能改value,和添加操作一样
// 如果是不存在的key,则为添加,存在的key则为修改
map.put("a", 11);
// 查,根据key获取value
System.out.println(map.get("a"));
System.out.println(map);
// 个数
System.out.println(map.size());
// 是否为空
System.out.println(map.isEmpty());
// 是否包含某个key
System.out.println(map.containsKey(""));
// 是否包含某个value
System.out.println(map.containsValue(""));
// 清空
map.clear();
}
}
不能直接遍历要引入新对象
遍历 :
import java.util.Collection;
import java.util.HashMap;
import java.util.Map.Entry;
import java.util.Set;
public class HashMap_02 {
public static void main(String[] args) {
HashMap map = new HashMap();
map.put("a1", 1);
map.put("a2", 2);
map.put("a3", 3);
map.put("a4", 4);
map.put("a5", 5);
map.put("a6", 6);
// values() 获取所有的value
Collection values = map.values();
for (Object object : values) {
System.out.println(object);
}
System.out.println("=========");
// 把key取出,保存在set中
Set set = map.keySet();
for (Object object : set) {
System.out.println(object + " : " + map.get(object));
}
System.out.println("===========");
// 把map转换为 多个entry对象 并保存在set中
Set entrys = map.entrySet();
for (Object entry : entrys) {
// 覆写toString 会以key=value的形式打印
// System.out.println(entry);
Entry obj = (Entry) entry;
System.out.println(obj.getKey()+" : "+obj.getValue());
}
}
}
第三种遍历方法可以有两种表现形式
第一种 :
当这种打印形式结果是
第二种 :
当这种打印形式结果是
2.5 TreeMap
底层代码主要是红黑树
Key类型必须一致,运行时会排序, 调用Compare方法, 当不一致时会报错, 而HashMap不会排序, 所以可以不一致.
TreeMap 使用方法跟TreeSet 一样
具体看 day19-CSDN博客
import java.util.TreeMap;
public class TreeMap_01 {
public static void main(String[] args) {
// 会按照key排序,所以使用treeMap时,key必须有两个比较器中任意一种
// 注意,因为TreeMap会排序,需要比较,所以类型必须一致
// 意味着 treeMap中必须保存同类型的数据
TreeMap map = new TreeMap();
map.put("a", 1);
map.put("a1", 1);
map.put("1a", 1);
map.put("2", 1);
map.put("10", 1);
System.out.println(map);
map.keySet();
map.entrySet();
map.values();
map.containsKey("");
map.containsValue("");
map.isEmpty();
map.clear();
map.size();
map.get("");
map.remove("");
}
}
3. 泛型(Generic)
3.1 概述
泛型 : 类型检查
没有使用泛型之前,结合可以存储任意类型的数据, 均会转型为Object类型
优缺点 :
优点 : 什么类型都可以放
缺点 : 由于什么都能放, 导致获取数据时,得到的是Object,想要使用对象特有属性时,需要强制 类型转换
使用泛型之后, 集合只能保存单一类型的数据
优缺点 :
优点 : 由于保存数据的类型一致,所以使用的时候,不需要向下转型
缺点 : 只能保存单一数据类型
注(泛型:只能写引用类型,不能写基本类型,如果要保存数字,应该写Integer类型(对应 的包装类))
3.2 使用方法
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
public class Generic_01 {
public static void main(String[] args) {
// 可以添加任何类型数据
List list = new ArrayList();
list.add("张三");
list.add(18);
list.add(95.5);
// 取出数据时,必须是Object类型
for (Object object : list) {
}
//泛型
// 只能添加String类型数据
List<String> list2 = new ArrayList<String>();
list2.add("a");
list2.add("a");
list2.add("a");
// list2.add(123);
// 取出数据时,是String,不需要我们再进行转换
for (String string : list2) {
}
// String默认按照ASCII码排序,需求是,按照对应的数值大小升序
TreeMap<String, Integer> map = new TreeMap<String, Integer>(
new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return Integer.parseInt(o1) - Integer.parseInt(o2);
}
});
map.put("11", 1);
map.put("2", 1);
map.put("1", 1);
map.put("10", 1);
map.put("3", 1);
System.out.println(map);
}
}
运行结果 :
3.3 注意
写基本类型时要用Integer 否则会报错
3.4 自定义泛型
public class Generic_02 {
public static void main(String[] args) {
MyClass myClass = new MyClass();
myClass.m1(1);
myClass.m1("xx");
MyClass<String> mm = new MyClass<String>();
mm.m1("xxx");
// mm.m1(123);
}
}
// 如果设置泛型后,不传入数据类型,则默认为Object类型
class MyClass<T> {
public void m1(T obj) {
System.out.println(obj);
}
}
4. 面试题
题目 :
给出一个Map,key是String类型,value是Integer类型
需求 : 按照value值,进行升序排序
import java.awt.List;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
/**
* 给出一个Map,key是String类型,value是Integer类型
*
* 需求 : 按照value值,进行升序排序
*/
public class Test_01_MianShiTi {
public static void main(String[] args) {
TreeMap<String, Integer> map = new TreeMap<String, Integer>();
map.put("a", 1);
map.put("a1", 2);
map.put("1a", 3);
map.put("bb", 11);
map.put("a3", 21);
System.out.println(map);
// 1 把map中键值队,封装到entry中,并取出并存储到Set中
Set<Entry<String, Integer>> set = map.entrySet();
// 2把set转存到List中
ArrayList<Entry<String, Integer>> list = new ArrayList<Entry<String, Integer>>(
set);
// 3 对ArrayList进行排序,排序时,按照value排序即可
list.sort(new Comparator<Entry<String, Integer>>() {
@Override
public int compare(Entry<String, Integer> o1,
Entry<String, Integer> o2) {
return o2.getValue() - o1.getValue();
}
});
System.out.println(list);
}
}
1. 把map中的键值对, 封装到entry中, 并取出存储到ArrayList中
2. 对ArrayList进行排序, 排序时, 按照value排序即可