1. Map
1.1 概述
Map是无序的,并且保存的是K-V键值对映射关系,其中K不能重复,V可重复
HashMap:底层是散列表
TreeMap : 底层是红黑树,元素必须按照一定的规则进行排序
映射关系: 比如 商品 和 购买数量,或者数据统计
"akshdkjhwqgheghgbsjkasdjaskhrjqw"统计每个字符出现的个数 使用 HashMap进行存储,字符做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值,叫哈希冲突
1.2 继承体系
1.3 常用方法
2. HashMap
2.1 使用方法
public static void main(String[] args) {
Map map = new HashMap();
// 支持K和V都是null,但没意义
map.put(null, null);
map.put("a", 1);
map.put("A", 2);
map.put('A', 3);
map.put('A', 4);
map.put(65, 5);
// 删除
map.remove("a");
// 修改,key不能修改,只能改value值,和添加操作一样
// key不存在,则为添加,key存在,则是修改
map.put("A", 22);
// 查询,根据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("a"));
// 是否包含某个value
System.out.println(map.containsValue("1"));
// 清空
map.clear();
}
2.2 遍历方法
public static void main(String[] args) {
Map map = new HashMap();
map.put("a1", 1);
map.put("a2", 2);
map.put("a3", 3);
map.put("a4", 4);
map.put("a5", 5);
// 打印输出的格式为key = value
System.out.println(map);
// 打印value值
// values() 获取所有的value
Collection values = map.values();
for (Object object : values) {
System.out.print(object + " ");
}
System.out.println();
// 打印key值
// 把key值取出保存在Set中
Set set = map.keySet();
for (Object object : set) {
System.out.print(object + " ");
}
System.out.println();
// 按指定格式输出
// 把map转换成entry对象,保存在set中
Set set2 = map.entrySet();
for (Object object : set2) {
// 默认会以 key = value 的形式输出
// System.out.println(object);
Entry entry = (Entry) object;
System.out.print(entry.getKey() + ":" + entry.getValue() + " ");
}
System.out.println();
// 箭头函数遍历map
map.forEach((x,y) -> {
System.out.println(x + ":" + y);
});
}
2.3 HashSet
当我们使用HashSet的时候,其实就等于是再使用HashMap
添加数据的时候,虽然调用的是HashSet的add方法,但是本质还是调用map的put方法
Ps : 在map中,put是添加操作
而 map中 需要保存的是k和v映射关系,所以在set中有一个变量保存了value的值
所以我们再进行set添加的时候,只操作了map中的key,value值我们不再关心
3. TreeSet
3.1 概述
会按照key排序,所以使用treeMap时,key必须有两个比较器中任意一种
注意,因为TreeMap会排序,需要比较,所以类型必须一致
意味着 treeMap中必须保存同类型的数据
3.2 使用方法
TreeMap map = new TreeMap();
map.put("a1", 1);
map.put("a2", 2);
map.put("a3", 3);
map.put("a4", 4);
map.put("a5", 5);
// 打印
System.out.println(map);
// 获取key值保存在set中
map.keySet();
// 将map保存在Entry中
map.entrySet();
// 获取value值
map.values();
// map中是否包含某个key值
map.containsKey("");
// map中是否包含某个value值
map.containsValue("");
// map是否为空
map.isEmpty();
// 清空
map.clear();
// 个数
map.size();
// 根据key值获取
map.get("");
// 删除
map.remove("");
// 添加
map.put("","");
4. 散列表
4.1 概述
散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。
4.2 底层逻辑
5. 泛型
5.1 概述
泛型 : 类型检查
没有使用泛型之前,集合中可以存储任意类型的数据,均会转型为Object类型
优点 : 什么都能放
缺点 : 由于什么都能放,导致获取数据时,得到的是Object,想要使用对象特有属性时,需要强制类型转换(向下转型)
使用泛型之后,集合中只能保存单一类型的数据
优点 : 由于保存数据的类型一致,所以使用的时候,不需要向下转型
缺点 : 只能保存单一数据类型
泛型:只能写引用类型,不能写基本类型,如果要保存数字,应该写Integer类型(对应 的包装类)
5.2 使用方法
public static void main(String[] args) {
List list = new ArrayList();
// 可以添加任意类型
list.add(1);
list.add("a");
list.add(3.14);
List<String> listStrings = new ArrayList<String>();
listStrings.add("123");
listStrings.add("abc");
// 添加String泛型之后只能添加字符串类型
// 添加其他类型会报错
// listStrings.add(123);
}
public static void main(String[] args) {
// String类型 默认是根据ASCII码来进行排序的
// 我们的需求是根据对应的数值大小来排序
Map<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("1", 1);
map.put("20", 2);
map.put("15", 3);
map.put("6", 4);
map.put("10", 5);
System.out.println(map);
}
5.3 注意
5.4 自定义泛型
定义泛型,使用大写字母A-Z表示,写什么都一样,都只是占位符而已,只不过 某些字符也有一些特殊的含义
E: Element 一般代表元素,而集合中的数据 我们叫元素,所以在集合中出现的泛型一股使用E表示
K : Key 表示键
V : value 表示值 K和V一般在散列表中出现(Map)
T:Type 表示一个java类型
N:表示Number
?: 表示不确定的类型
如果规定了泛型,但是使用的地方没有指定泛型,则默认为Object类型
public static void main(String[] args) {
Myclass myclass = new Myclass();
myclass.m("a");
myclass.m(123);
Myclass<String> myclass2 = new Myclass<String>();
myclass2.m("abc");
// 传入数值 报错
// myclass2.m(123);
}
}
class Myclass<T>{
public void m(T obj) {
System.out.println(obj);
}
5.5 Map 以 value值排序
public static void main(String[] args) {
Map<String, Integer> map = new TreeMap<String, Integer>();
map.put("a1", 3);
map.put("a2", 1);
map.put("a3", 4);
map.put("a4", 5);
map.put("a5", 2);
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);
// 对ArrayList进行排序,排序时,按照value排序即可
list.sort(new Comparator<Entry<String, Integer>>() {
@Override
public int compare(Entry<String, Integer> o1,
Entry<String, Integer> o2) {
return o1.getValue() - o2.getValue();
}
});
System.out.println(list);
}