本文笔记来源于本人自学尚硅谷java最新基础课程而来
1. 集合框架的概述
1.1 数据存储的容器
内存层面需要针对于多个数据进行存储。
此时,可以考虑的容器有:集合Collection 和 数组
1.2 数组的特点和弊端
- 特点: #java了解
- 数组一旦初始化,其长度就是确定的。
- 数组中的多个元素是依次紧密排列的,有序的,可重复的
- (优点)数组一旦初始化完成,其元素的类型就是确定的,不是此类型的元素,就不能添加到此数组中。
int[] arr = new int[10]; arr[0] = 1; arr[1] = "AA"; //编译会报错 Object[] arr1 = new Object[10]; arr1[0] = new String(); arr1[1] = new Date();
(优点)元素的类型既可以是基本数据类型,也可以是引用数据类型
- 弊端:
- 数组一旦初始化,其长度就不可变了
- 数组中存储数据特点的单一性。对于无序的、不可重复的场景的多个数据就无能为力了
- 数组中可用的方法、属性极少。具体的需求,都需要自己来组织相关的代码逻辑。
- 针对于数组中元素的输出、插入操作,性能较差
#### 1.3 Java集合框架体系(java.util包下)(重点)
```java
java.util.Collection 存储一个个的数据
子接口:List ---> 有序的、可重复的数据 类似于 “动态”数组
实现类: ArrayList(主要实现类)、LinkedList、Vector
子接口:Set ---> 无序的、不可重复的数据 类似于数学上的集合
实现类: HashSet(主要实现类)、 LinkedHashSet、TreeSet
java.util.Map 存储一对一对的数据(key-value键值对,(x1,y1)、(x2,y2) 类似于数学上的 y = f(x) ,
实现类:HashMap(主要实现类)、LinkedHashMap、TreeMap、Hashtable、Properties
1.4 学习的程度把握:(逐步递进的)
-
掌握Collection接口的主要方法(15个),主要实现类的方法,会实例化,会选取合适的实现类
-
明确不同实现类的区别
-
针对常用的实现类知道底层的原码,熟悉常见的数据结构(第14章讲解)
2. Collection的常用方法
2.1 常用方法:(Collection中定义了15个抽象方法。这些方法需要熟悉!)
add (Object obj)
addAll(Collection coll)
clear()
isEmpty()
size()
contains(Object obj)
containsAll(Collection coll)
retainAll(Collection coll) //只保留交集,及两个集合中相同的部分!!!
remove(Object obj)
removeAll(Collection coll) //删除交集
hashCode()
equals()
toArray()
---
iterator()
2.2 集合与数组的相互转换:
- 针对于方法的一些参数
集合—>数组: toArray()
数组—>集合: Arrays.asList(Object … obj) //注意是对象传入!!! 返回的是一个List集合类
//数组--->集合
Object[] o1 = new Object[]{"aa",1312,"new",new Person("jerry",12)};
Collection coll1 = Arrays.asList(o1);
System.out.println(coll1);
Integer[] i1 = new Integer[]{1,2,3};
Collection coll2 = Arrays.asList(i1);
System.out.println(coll2);
System.out.println(coll2.size()); //3
int[] i2 = new int[]{1,2,3};
Collection coll3 = Arrays.asList(i2);
System.out.println(coll3);
System.out.println(coll3.size()); //1
2.3 向Collection中添加元素的要求:
要求元素所属的类必须要重写equals()方法!!!
原因:
Collection中的一些方法(如:contains() / remove() )在使用时,要调用元素所在类的equals()方法
若没有重写,则比较的地址值,无法删除集合中字面上相同的元素
如:
Person p1 = new Person("lihua",25);
Person p2 = new Person("lihua",25);
Collection coll = new ArrayList();
coll.add(p1);
coll.remove(p2); //无法删除,无法找到该对象,因为此时比较的是地址值
3. 迭代器和增强for循环
3.1 迭代器(Iterator)的作用?
- 用来遍历集合元素的
- 补充:
- 迭代器是一个接口(java.util.Iterator)
- 是设计模式的一种
- 不负责数据的存储,赋值集合类的遍历
3.2 如何获取迭代器(Iterator)对象?
Iterator iterator = coll.iterator();
3.3 如何实现遍历(代码实现)
while(iterator.hasNext()){
System.out.println(iterator.next());
//①指针下移;②将下移后集合位置上的元素返回
}
3. 4 增强for循环(foreach循环)的使用(jdk5.0新特性)
-
作用
遍历数组和集合
-
格式
for(数组或集合中的元素类型 临时变量: 数组或集合){
操作临时变量的输出
}
- 说明:
- 针对于集合来说,增强for循环的底层仍然使用的是迭代器
- 增强for循环的执行过程中,是讲集合或数组中的元素依次赋值给临时变量
- 注意!!!
- 循环体中对临时变量的修改,可能不会导致原有集合或数组中元素的修改
4. List
4.1 List接口中存储数据的特点
用于储存有序的、可以重复的数据 —> 使用List代替数组,“动态”数组 (ArrayList)
4.2 List中的常用方法
第1波:Collection中的15个方法
第2波:
- 小结(必须记住!!!) #java记忆点
- 增: add(Object obj) / addAll(Collection coll)
- 删: remove(Object obj) / remove(int index) 注意数据类型!!!
- 改: set(int index, Object ele)
- 查: get(int index)
- 插: add(int index ,Object ele) / addAll(int index, Collection eles)
- 长度: size()
- 遍历: iterator() / 增强for循环 / for循环
4. 3 List及其实现类特点
- java.util.Collection:储存一个个的数据
- 子接口,List:储存 有序的,可重复的数据(“动态”数组)
- ArrayList:
List的主要实现类;线程不安全,效率高;底层使用Object[]数组进行存储
在添加数据、查找数据时,效率较高(直接索引可以找到,复杂度为o(1));
在插入、删除数据时,效率较低(一个个前移/后移,复杂度为o(n));
- LinkedList:
底层使用双向链表的方式进行存储; 在对集合中的数据进行频繁的删除、插入操作时,效率较高(对链进行操作,复杂度为o(1));
在添加数据、查找数据时,效率较低(根据链一个个的查,复杂度为o(n))
- Vector:
List的古老实现类;线程安全的,效率低;底层使用Object[]数组进行存储
5. Set(熟悉)
熟悉熟悉就可以了
5.1 Set及其实现类特点
- java.util.Collection
- 子接口:set ---> 存储无序的、不可重复的数据(高中学习的集合)
- 实现类:HashSet(主要实现类) ---> 底层使用的是HashMap,即使用数组、单向链表和红黑树结构进行存储
- 其子类:LinkedHashSet ---> 是HashSet的子类,在现有结构的基础上又加上了一组双向链表。
即:我们可以按照添加元素的顺序实现遍历。便于频繁的查询操作
- TreeSet:底层使用红黑树存储。可以按照添加的元素的指定的属性的大小顺序进行遍历
5.2 开发中的使用频率及场景
- 较List Map来说,Set的使用频率较低
- 原来过滤重复的数据
5.3 Set中常用方法
- 即为Collection中声明的15个抽象方法。没有新增的方法
5.4 Set中无序性、不可重复性的理解 #java注意点
-
无序性:
- != 随机性
- 添加元素的顺序和遍历元素的顺序不一致,是不是就是无序性呢?不是的
- 到底声明是无序性? 与添加的元素的位置有关,不想ArrayList那样是依次紧密排列的
- 这里是根据添加元素的哈希值,计算的其在数组中的存储位置。此位置不是依次排列的,表现为无序性!!!
-
不可重复性
- 添加到Set中的元素是不可相同的。
- 比较的标准,先判断hashCode()的到的哈希值,若相同就在判断equals()得到的boolean类型的结果
- 哈希值相同&&equals返回true,则元素是相同的。
5.5 添加到HashSet/LinkedHashSet中元素的要求:(由5.3引出)
- 要求元素的equals() 和 hashCode() 方法必须重写
- 要求两个方法保持一致性,我们只需要在IDEA中自动生成这两个方法即可
5.6 TreeSet的使用(了解即可,主要熟悉两个比较器)
6.1 底层的数据结构:
- 红黑树结构
6.2 添加数据后的特点:
- 可以按照添加的元素中,指定的属性的大小顺序,进行遍历
6.3 向TreeSet中添加的元素的要求:
- 添加到TreeSet中的元素必须是一个类型的对象,否则会报ClassCastException
- 添加的元素需要考虑排序:自然排序 / 定制排序
6.4 判断数据是否相同的标准
- 不用在考虑hashCode()和equals()方法了,也就意味着添加到TreeSet中的元素所在的类不用重写这两个方法
- 比较元素的带下的标准就是考虑自然排序/定制排序中的compareTo(Object obj)/compaer(Object obj1,Object obj2)的返回值
- 如果返回值为0,则相同,所以后一个相等的元素就不能添加到TreeSet中了
6. Map
6.1 Map及其实现类对比
储存一堆一堆的数据(entry:key-value 键值对,类似于高中的函数)
- HashMap(主要实现类):线程不安全,效率高;可以添加null的key和value值;底层使用数组,单向链表和红黑树结构存储(jdk8)
- LinkedHashMap :是HashMap的子类,在HashMap使用的数据结构的基础上,增加了一对双向链表,用于记录添加的元素的先后顺序,进而我们在遍历元素的时候,就可以按照添加的顺序显示
开发中,对于频繁的遍历操作,建议使用此类- TreeMap :底层使用红黑树储存;可以按照添加的key-value中的key元素的制定的属性的大小顺序进行遍历,需要考虑使用自然排序和定制排序
- Maptable :古老实现类;线程安全的,效率低;不可以添加null的key和value;底层使用数组和单向链表储存
- Properties :其key和value都是String类型的。常用来处理属性文件
[面试题] #java重点
- 区分HashMap和Hashtable
- 区分HashMap和LinkedHashMap
- HashMap的底层实现(①new HashMap;②put(key,value))
6.2 HashMap中元素的特点(熟悉!!!)
-
所有的key彼此之间是不可重复的、无序的。所以key就构成了一个Set集合。—> key所在的类要求重写hashCode()和equals()方法
-
所有的value彼此之间是可重复、无序的。所以value就构成了一个Collection集合。 —> value所在的类要重写equals()方法
-
一个key-value就构成了一个entry(node)
-
所有的entry彼此之间是不可重复的、无序的。所以entry就构成了一个Set集合。
6.3 Map中的常用方法
小结:(记住!!!)
- 增: put(Object key,Object value) / putAll(Map m)
- 删: Object remove(Object key)
- 改: put(Object key,Object value) / putAll(Map m)
- 查: Object get(Object key)
- 插: 无序的,无法插入
- 长度: size()
- 遍历:
- 遍历key集: Set keySet()
- 遍历value集: Collection values()
- 遍历entry集: Set entrySet()
6.4 TreeMap的使用(了解)
- 底层使用红黑树结构
- 可以按照添加的key-value中的key元素的指定的属性的大小顺序进行遍历
- 需要考虑使用自然排序或导致排序
- 要求!!! 添加到key中的元素必须是一个类型的对象
6.5 Hashtable与Properties的使用(重点的,在io中比较重要)
-
Properties是Hashtable的子类,其key和value都是String类型的,常用来处理属性文件。
-
Properties的使用实例
public class PropertiesTest { @Test public void test() throws IOException { //注意:因为设计到流的操作,为了确保流能关闭,建议使用try-catch-finally //方式1:数据和代码耦合度高;如果修改的话,需要重写的编译代码、打包发布,繁琐 //数据 // String name = "Tom"; // String password = "abc123"; //代码:用于操作name,password //... //方式2:将数据封装到具体的配置文件中,在程序中读取配置文件中的信息。实现了 //数据和代码的解耦;由于我们没有修改代码,就省去了重新编译和打包的过程。 File file = new File("info.properties"); //注意,要提前创建好 // System.out.println(file.getAbsolutePath()); FileInputStream fis = new FileInputStream(file); Properties pros = new Properties(); pros.load(fis); //加载流中的文件中的数据 //读取数据 String name = pros.getProperty("name"); String pwd = pros.getProperty("password"); System.out.println(name + ":" + pwd); fis.close(); } }
7. Collections工具类的使用
7.1 Collections概述
- Collection是一个操作Set、List、Map等集合的工具类
7.2 常用方法
排序操作:
- reverse(List):反转 List 中元素的顺序
- shuffle(List):对 List 集合元素进行随机排序
- sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
- sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
- swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换
查找
- Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
- Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素
- Object min(Collection):根据元素的自然顺序,返回给定集合中的最小元素
- Object min(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最小元素
- int binarySearch(List list,T key)在List集合中查找某个元素的下标,但是List的元素必须是T或T的子类对象,而且必须是可比较大小的,即支持自然排序的。而且集合也事先必须是有序的,否则结果不确定。
- int binarySearch(List list,T key,Comparator c)在List集合中查找某个元素的下标,但是List的元素必须是T或T的子类对象,而且集合也事先必须是按照c比较器规则进行排序过的,否则结果不确定。
- int frequency(Collection c,Object o):返回指定集合中指定元素的出现次数
复制、替换
- void copy(List dest,List src):将src中的内容复制到dest中
- boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换 List 对象的所有旧值
- 提供了多个unmodifiableXxx()方法,该方法返回指定 Xxx的不可修改的视图。
添加
- boolean addAll(Collection c,T... elements)将所有指定元素添加到指定 collection 中。
同步
- Collections 类中提供了多个 synchronizedXxx() 方法,该方法可使将指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题
实例:扑克牌例子
public class Exer {
public static void main(String[] args) {
String[] num = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
String[] color = {"方片♦","梅花♣","红桃♥","黑桃♠"};
ArrayList poker = new ArrayList();
//组牌(每个花色对应不同的数字,最后加上大王和小王)
for (int i = 0; i < color.length; i++) {
for (int j = 0; j < num.length; j++) {
//把每个牌都放进去
poker.add(color[i] + num[j]);
}
}
poker.add("大王");
poker.add("小王");
//洗牌
Collections.shuffle(poker);
//发牌
List Tom = new ArrayList();
List Jerry = new ArrayList();
List me = new ArrayList();
List last = new ArrayList();
for (int i = 0; i < poker.size(); i++) {
if(i> poker.size()-4){
last.add(poker.get(i));
}
if (i%3==0){
Tom.add(poker.get(i));
}else if (i%2==0){
Jerry.add(poker.get(i));
}else if (i%1==0){
me.add(poker.get(i));
}
}
System.out.println("Tom:");
System.out.println(Tom);
System.out.println("Jerry:");
System.out.println(Jerry);
System.out.println("me:");
System.out.println(me);
System.out.println("last:");
System.out.println(last);
//进一步思考如何将得到的牌排好序,
//提示:
//HashMap,其中key为下标,value为poker
}
}
7.3 面试题:区分Collection 和 Collections(需要知道,其他了解)
Collection:集合框架中的用于存储一个一个元素的接口,又分为List和Set等子接口。
Collections:用于操作集合框架的一个工具类。此时的集合框架包括:Set、List、Map