文章目录
- Collection-单列集合特点
- List
- ArrayList
- LinkedList
- Vecter
- Set
- HashSet
- TreeSet
- Map-键值对集合特点
- Map常用API
- put添加细节
- remove
- Map的三种遍历方式
- 1.通过键找值
- 2.通过"键值对"
- 3.Lambda表达式
- foreach源码
- HashMap
- 需求
为什么要使用泛型
泛型的优点
1.集合中存储的元素类型统一了
2.从集合中取出来的元素类型是泛型指定的类型,不需要进行大量的“向下转型”
泛型的确定
1.导致集合中存储的元素缺乏多样性。
Collection-单列集合特点
List
ArrayList
ArrayList特点
1.ArrayList层地采用了数组的数据结构;
2.ArrayList是非线程安全的;
3.ArrayList初始化容量是10(底层先创建了一个长度为0的数组,当添加第一个元素的时候,初始化容量10);
4.ArrayList底层是Object类型的数组Object[]
5.扩容1.5倍
6.建议给定一个预估计的初始化容量,减少数组的扩容次数,这是ArrayList集合比较重要的优化策略
数组的优点
1.数组的检索效率比较高。
为什么数组的检索效率高?
数组中每个元素占用空间大小相同,内存地址是连续的,知道首元素内存地址,然后知道下标,通过数学表达式计算出元素的内存地址,所以检索的效率高。
2.数组向数组末尾添加元素的效率还是很高的,也就是数组的添加效率很高。
数组的缺点
1.数组随机增删元素效率比较低
LinkedList
链表数据结构的特点
链表的优点:
1.由于链表上的元素在空间存储上内存地址不连续,所以随机增删元素的时候不会有量元素的位移,因此随机增删的效率高。在以后得开发中,如果遇到随机增删集合中元素的业务比较多时,建议使用LinkedList
链表的缺点
1.不能通过数学表达式计算被查找元素的内存地址,每一次查找都是从头节点开始遍历,直到找到为止,所以LinkedList集合检索/查找的效率较低。
LinkedList特点
1.LinkedList底层采用了双向链表数据结构
Vecter
Vecter特点
1.Vector底层也采用了数组的数据结构是线程安全的。
2.Vector底层方法都使用了synchronized关键字修饰虽然线程安全但效率不高,一般使用较少了。
Set
HashSet
HashSet特点:
1.HashSet创建时实际上是底层new了一个HashMap集合,也就意味着HashSet是将数据存储到了HashMap集合中了,HashMap是一个哈希表数据结构;
TreeSet
TreeSet的父级接口是SortSet,SortSet继承了Set接口,接口是抽象的,无法实例化。
TreeSet特点
1.TreeSet也称可排序集合
2.无顺不可重复,但存储的元素可以自动按照大小顺序或字幕A~Z排序
3.无序:指得是元素存进去的顺序和取出来的顺序不一样,并且没有下标。
4.TreeSet创建的时候,底层new了一个TreeMap,TreeMap底层使用了二叉树数据结构
Map-键值对集合特点
Map-键值对集合特点:
1.Map是以key(键)和value(值)的方式存储数据:键值对;
2.key(键)不能重复,value(值)可以重复;
3.key(键)和value(值)都是引用数据类型,存储对象的内存地址;
4.key(键)和value(值)一一对应,每一个键只能找到自己对应的值,key起到主导的地位,value是key的一个附属品。
5.key(键)和value(值)是一个整体,称为"键值对"或者"键值对对象",在Java中叫做"Entry对象"。
Map常用API
Map接口中常用方法:
* V put(K key,V value) 向Map集合中添加键值对
* V get(Object key) 通过Key获取value
* void clear() 清空Map集合
* boolean containsKey(Object key) 判断Map中是否包含某个Key
* boolean containsValue(Object value) 判断Map中是否包含某个value
* boolean isEmpty() 判断Map集合中元素个数是否为0
* Set<K> keySet() 获取Map集合中所有的key(所有的键是一个set集合)
* V remove(Object key) 通过key删除键值对
* int size() 获取Map集合中键值对的个数
* Collection<V> values() 获取Map集合中所有的value,返回一个Collection
代码中选中Map关键字Ctrl+B去到Map的源码中
put添加细节
1.put对象是,Map有返回值
put:添加/覆盖
在添加数据的时候,如果键不存在,那么直接把键值对对象提提添加到map集合当中,方法返回null
在添加数据的时候,如果键是存在的,那么会把原有的键值对对象覆盖,会把被覆盖的值进行返回。
public class MapApi {
public static void main(String[] args) {
Map<String,String> m = new HashMap<>();
String value0 = m.put("郭靖","黄蓉");
System.out.println(value0);
m.put("韦小宝","沐剑屏");
m.put("杨过","小龙女");
m.put("尹志平","小龙女");
//向相同的键里再次添加元素
String value = m.put("韦小宝","双儿");
System.out.println(value);
System.out.println(m);
}
}
remove
remove时也有返回值,返回的是被删除的键值对对象的值。
public class MapTest01 {
public static void main(String[] args) {
Map<Integer,String> map = new HashMap<>();
//1.向Map中添加key-value
map.put(101,"zhangsan");
map.put(202,"lisi");
map.put(303,"wangwu");
map.put(404,"zhaoliu");
System.out.println(map);
//2.获取添加到Map中的key-value的个数
System.out.println("2.Map中所有键值对的个数:"+map.size());
//3.通过key取value
String value = map.get(303);
System.out.println("3.通过key取到的value为:"+value);
//4.获取所有的value
Collection<String> values = map.values();
System.out.println("4.values()获取Map中的所有value:"+values);
//foreach values
for(String str : values){
System.out.println("5.遍历取出:"+str);
}
//6.获取所有的key
Set<Integer> keys = map.keySet();
System.out.println("6.keySet()返回Map中所有的key:"+keys);
//7.判断是否包含某个key和value
System.out.println("7.判断是否包含202的key的结果为:"+map.containsKey(202));
System.out.println("8.判断是否包含leilei的value的结果为:"+map.containsValue("leilei"));
//9.通过key删除key-value
map.remove(404);
System.out.println("9.调用remove()方法后的键值对的数量:"+map.size());
//10.清空Map集合
map.clear();
System.out.println("10.clear()后键值对的数量为:"+map.size());
}
}
{404=zhaoliu, 101=zhangsan, 202=lisi, 303=wangwu}
2.Map中所有键值对的个数:4
3.通过key取到的value为:wangwu
4.values()获取Map中的所有value:[zhaoliu, zhangsan, lisi, wangwu]
5.遍历取出:zhaoliu
5.遍历取出:zhangsan
5.遍历取出:lisi
5.遍历取出:wangwu
6.keySet()返回Map中所有的key:[404, 101, 202, 303]
7.判断是否包含202的key的结果为:true
8.判断是否包含leilei的value的结果为:false
9.调用remove()方法后的键值对的数量:3
10.clear()后键值对的数量为:0
Map的三种遍历方式
1.通过键找值
public static void main(String[] args) {
Map<String,String> m = new HashMap<>();
m.put("郭靖","黄蓉");
m.put("韦小宝","沐剑屏");
m.put("杨过","小龙女");
System.out.println(m);
Set<String> keys = m.keySet();
for(String str : keys){
String key = str;
String value = m.get(key);
System.out.println(key + "=" + value);
}
}
2.通过"键值对"
public static void main(String[] args) {
Map<String,String> m = new HashMap<>();
m.put("郭靖","黄蓉");
m.put("韦小宝","沐剑屏");
m.put("杨过","小龙女");
System.out.println(m);
Set<Map.Entry<String, String>> entries = m.entrySet();
for (Map.Entry e : entries){
System.out.println(e.getKey()+"="+e.getValue());
}
}
Ctrl+Alt+V自动生成方法的返回值类型,或者在方法名后加.var也可以
3.Lambda表达式
public static void main(String[] args) {
Map<String,String> m = new HashMap<>();
m.put("鲁迅","我没说过这句话");
m.put("诸葛亮","悠悠苍天,何薄于我");
m.put("曹操","我笑诸葛无谋,周瑜少智");
System.out.println(m);
m.forEach(new BiConsumer<String, String>() {
@Override
public void accept(String s, String s2) {
System.out.println(s +"="+s2);
}
});
//改写为lambda
m.forEach((s, s2) -> System.out.println("我是lambda:"+s +"="+s2));
}
foreach源码
foreach的缺点
foreach底层也是使用的增强for循环,它没有下标,不能通过下标查询元素
HashMap
HashMap底层原理
1.HashMap底层是哈希表结构
2.依赖hashCode方法和equals方法保证键的唯一
3.如果键存储的是自定义对象,需要重写hashCode和equals方法
如果值存储字定义对象,不需要重写hashCode和equals方法
需求
创建一个HashMap集合,
1.键是学生对象(Student),值是籍贯(String).
2.存储三个键值对元素,并遍历
3.要求:同姓名同年龄认为是同一个学生。
public class Student {
private int age;
private String name;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(age, name);
}
@Override
public String toString() {
return "Student{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
getter setter省略
......
}
public class HashMapTest {
public static void main(String[] args) {
HashMap<Student,String> map = new HashMap<>();
//1.实例化学生对象
Student student0 = new Student(23,"张三");
Student student1 = new Student(24,"李四");
Student student2 = new Student(25,"王五");
Student student3 = new Student(25,"王五");
map.put(student0,"湖北");
map.put(student1,"广东");
map.put(student2,"河南");
map.put(student3,"福建");
//遍历map对象
Set<Student> students = map.keySet();
for(Student stu : students){
String value = map.get(stu);
System.out.println(stu +"=>"+value);
}
}
}