集合架构
集合架构
单列集合collection(接口)
一.list(接口)
添加的元素是有序,可重复,有索引
- ArrayList(实现类)
- LinkedList(实现类)
- Vector(淘汰)(实现类)
二.Set(接口)
添加的元素是无序,不重复,无索引
- HashSet (实现类) LinkedHashSet(实现类)
- TreeSet(实现类)
Collection

Collection是一个接口我们不能直接创建他的对象
所以,我们在学习他的方法时,只能创建他实现类的对象
实现类:ArrayList
A01_CollectionDemp2.java
package org.Mycollection;
import java.util.ArrayList;
import java.util.Collection;
public class A01_CollectionDemo1 {
public static void main(String[] args){
Collection<String> coll = new ArrayList<>();
//1.添加元素
//细节:如果我们要往List系列中添加数据,那么方法永远返回true,因为List系列是允许元素重复的
//细节:如果我们要往Set系列集合中添加数据,如果当前要添加的元素不存在,方法返回true,表示添加成功,如果当前要添加的元素已经存在,方法返回false,表示添加失败
//因为Set系列的数据不允许重复
coll.add("aaa");
coll.add("bbb");
coll.add("ccc");
System.out.println(coll);
//2.清空
//coll.clear();
System.out.println(coll);
//3.删除
//细节:因为Collection里面定义的是共性的方法,所以此时不能通过索引删除。只能通过元素的对象进行删除。
//细节:方法会有一个布尔类型的返回值,删除成功返回true,删除失败返回false
//如果要删除的元素不存在,就会删除失败。
System.out.printf("", coll.remove("aaa"));
System.out.println(coll);
//4.判断元素是否包含
//细节:底层是依赖equals方法进行判断是否存在的
//所有,如果集合中存储的是自定义对象,也想通过contains方法来判断是否包含,那么在javabean类中,一定要重写equals方法
boolean result1 = coll.contains("bbb");
System.out.println(result1);
//5.判断集合是否为空
boolean result2 = coll.isEmpty();
System.out.println(result2);//flase
//6.获取集合的长度
coll.add("ddd");
int size = coll.size();
System.out.println(size);
}
}
isEmpty 判断条件是否没有任何元素
A01_CollectionDemp2.java
package org.Mycollection;
import java.util.ArrayList;
import java.util.Collection;
public class A01_CollectionDemo2 {
public static void main(String[] args) {
//1.创建集合的对象
Collection<Student> coll = new ArrayList<>();
//2.创建三个学生对象
Student s1 = new Student("zhangsan",22);
Student s2 = new Student("lisi",22);
Student s3 = new Student("wangwu ",22);
//3.把学生添加到集合中
coll.add(s1);
coll.add(s2);
coll.add(s3);
//4.判断集合中,某一个学生对象是否包含
Student s4 = new Student("zhangsan",22);
//如果同姓名和同年龄,就认为是同一个学生
//因为contains方法在底层依赖equals方法进行判断对象是否一致的。
//如果存在的是自定义对象,没有重写equals方法,那么默认使用Object类中的equals进行判断,而Object类中equals方法,依赖地址值进行判断。
//需求:如果同姓名和同年龄,就认为是同一个学生。
//所以,需要在自定义的Javabean类中,重写equals方法就可以了。
System.out.println(coll.contains(s4));//true
}
}
Collection的遍历方式


for遍历只能List用,Set用不了
迭代器不依赖索引
迭代器遍历


package org.Mycollection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class A03_CollectionDemo3 {
/*
* Collection系列集合的三种通用的遍历方式:
* 1.迭代器遍历
* 2.增强for遍历
* 3.lambda表达式遍历
*
* 迭代器遍历相关的三个方法:
* Iterator<E> itereator() : 获取一个迭代器对象
* boolean hasNext() :判断当前指向的位置是否还有元素
* E next() :获取当前指向的元素并移动指针*/
public static void main(String[] args) {
//1.创建集合并添加元素
Collection<String> coll = new ArrayList<>();
coll.add("aaa");
coll.add("bbb");
coll.add("ccc");
coll.add("ddd");
//2.获取迭代器对象
//迭代器就好比是一个箭头,默认指向集合的0索引处
Iterator<String> it = coll.iterator();
//3.利用循环不断的去获取集合中的每一个元素
while(it.hasNext()){
//4.next方法的两件事情:获取元素并移动指针
String next = it.next();
System.out.println(next);
}
}
}
迭代器的细节注意点
package org.Mycollection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class A04_CollectionDemo4 {
/*
* 迭代器的细节注意点
* 1.报错NoSuchElementExeption
* 2.迭代器遍历完毕,指针不会复位
* 3.循环中只能使用一次next方法
* 4.迭代器遍历时,不能用集合的方式进行增加或者删除*/
public static void main(String[] args) {
//1.创建集合并添加元素
Collection<String> coll = new ArrayList<>();
coll.add("aaa");
coll.add("bbb");
coll.add("ccc");
coll.add("ddd");
//2.获取迭代器对象
//迭代器就好比是一个箭头,默认指向集合0索引处
Iterator<String> it = coll.iterator();
//3.利用循环不断的去获取集合中的每一个元素
while (it.hasNext()) {
//4.next方法的两件事情:获取元素并移动指针
String str = it.next();
System.out.println(str);
}
//当上面的循环结束后,迭代器的指针已经指向了最后没有元素的位置
// System.out.println(it.next());//NoSuchElementExeption
//迭代器遍历完毕后,指针不会复位
System.out.println(it.hasNext());
//如果我们要继续第二次遍历集合,只能再次获取一个新的迭代器对象
Iterator<String> it2 = coll.iterator();
while (it2.hasNext()) {
String str = it2.next();
System.out.println(str);
}
}
}
package org.Mycollection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class A05_CollectionDemo5 {
/*
* 迭代器的细节注意点
* 1.报错NoSuchElementExeption
* 2.迭代器遍历完毕,指针不会复位
* 3.循环中只能使用一次next方法
* 4.迭代器遍历时,不能用集合的方式进行增加或者删除
* 暂时当做一个结论先记忆,在今天我们会讲解源码再来详细分析
* 如果我实在要删除,那么可以用迭代器提供的remove方法进行删除
* 如果我要添加,暂时没有办法*/
public static void main(String[] args) {
//1.创建集合并添加元素
Collection<String> coll = new ArrayList<>();
coll.add("aaa");
coll.add("bbb");
coll.add("ccc");
coll.add("ddd");
coll.add("eee");
//2.获取迭代器对象
//迭代器就好比是一个箭头,默认指向集合0索引处
Iterator<String> it = coll.iterator();
//3.利用循环不断的去获取集合中的每一个元素
while (it.hasNext()) {
//4.next方法的两件事情:获取元素并移动指针
String str = it.next();
if("bbb".equals(str)){
//coll.remove("bbb");
it.remove();
}
System.out.println(coll);
}
}
}
迭代器小结

增强for遍历

快速生成方式:
集合的名字 + for 回车

Lambda表达式遍历

package org.Mycollection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Consumer;
public class A07_CollectionDemo7 {
public static void main(String[] args){
/*Collection系列集合三种通用的遍历方式:
1.迭代器遍历
2.增强for遍历
3.1ambda表达式遍历
1ambda表达式遍历:
default void forEach(Consumer<? super T> action):
*/
//1.创建集合并添加元素
Collection<String> coll = new ArrayList<>();
coll.add("zhangsan");
coll.add("lisi");
coll.add("wangwu");
//2.利用匿名内部类的形式
//底层原理:
//其实也会自己遍历集合,依次得到每一个元素
//把得到的每一个元素,传递的给限免得到accept方法
//s依次表示集合中的每一个数据
coll.forEach(new Consumer<String>() {
@Override
//s依次表示集合中的每一个数据
public void accept(String s) {
System.out.println(s);
}
});
//lambda表达式
coll.forEach((String s)->{
System.out.println(s);
}
);
//简化后
coll.forEach( s->System.out.println(s));
}
}
lamdba表达式 小结

List集合


List系列集合中两个删除的方法
package org.a02mylist;
import java.util.ArrayList;
import java.util.List;
public class A02_ListDemo2 {
public static void main(String[] args) {
//List系列集合中两个删除的方法
//1.直接删除元素
//2.通过索引进行删除
//1.创建集合并添加元素
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
//2.删除元素
//请问:此时删除的是1这个元素还是1索引上的元素
//为什么?
//因为我们在调用方法的时候,如果方法出现了重载
// 优先调用,实参和形参类型一致的那个方法
// list.remove(1);
//手动装箱,手动把基本数据类型的1,变成Integer类型
Integer i = Integer.valueOf(1);
list.remove(i);
System.out.println(list);
}
}
package org.a02mylist;
import java.util.ArrayList;
import java.util.List;
public class A01_ListDemo1 {
public static void main(String[] args) {
/*
List系列集合独有的方法
void add(int index,E element) 在此集合中的指定位置插入指定的元素
E remove(int index) 删除指定索引处的元素,返回被删除的元素
E set(int index,E element 修改指定索引处的元素,返回被修改的元素
E get(int index) 返回指定索引处的元素 */
//1.创建一个集合
List<String> list = new ArrayList<>();
//2.添加元素
list.add("aaa");
list.add("bbb");
list.add("ccc");
//void add(int index,E element) 在此集合中的指定位置插入指定的元素
//细节:原来索引上的元素会依次往后移
list.add(1,"QQQ");
//E remove(int index) 删除指定索引处的元素,返回被删除的元素
String remove = list.remove(0);
System.out.println(remove);//aaa
//E set(int index,E element 修改指定索引处的元素,返回被修改的元素
String result = list.set(0, "WWW");
System.out.println(result);
//E get(int index) 返回指定索引处的元素 */
String s = list.get(1);
System.out.println(s);
//3.打印集合
System.out.println(list);
}
}
List集合的遍历方式
五种遍历方式

package org.a02mylist;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.function.Consumer;
public class A03_ListDemo3 {
public static void main(String[] args) {
/*List系列集合的五种遍历方式:
1.迭代器
2.列表迭代器
3.增强for
4.Lambda表达式
5.普通for循环*/
//创建集合并添加元素
List<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
//1.迭代器
/* Iterator<String> it = list.iterator();
while (it.hasNext()){
String str = it.next();
System.out.println(str);
}
*/
//2.增强for
//下面的变量s,其实就是一个第三方的变量而已
//再循环的过程中,依次表示集合中的每一个元素
/* for (String s : list) {
System.out.println(s);
}
*/
//3.lamdba表达式
//forEach方法的底层其实就是一个循环遍历,循环得到集合中的每一个元素
//并把每一个元素传递给下面的accept方法
//accept方法的形参s,依次表示集合中的每一个元素
// list.forEach( s -> System.out.println(s) );
//4.普通for遍历
//size方法跟get方法还有循环结合的方式,利用索引获取到集合中的每一个元素
/* for (int i = 0; i < list.size(); i++) {
//i:依次表示集合总的每一个数列
String s = list.get(i);
System.out.println(s);
}
*/
//5.列表迭代器
//获取一个列表迭代器的对象,里面的指针默认也是指向0索引的
//额外添加了一个方法,在遍历的过程中可以添加元素
ListIterator<String> it = list.listIterator();
while(it.hasNext()){
String str = it.next();
if ("bbb".equals(str)) {
//qqq
it.add("qqq");
}
System.out.println(list);
}
}
}
list集合遍历小结

数据结构![image-20251023211544028]()





数据结构小结

ArrayList集合




LinkedList集合

**

迭代器源码解析

泛型深入

package org.a04mygenerics;
import java.util.ArrayList;
import java.util.Iterator;
public class GenricsDemo1 {
public static void main(String[] args) {
//没有泛型的时候,集合如何存储数据
//结论:
//如果我们没有给集合指定类型,默认认为所有的数据类型都是Object类型
//此时可以往集合添加任意的数据类型
//带来一个坏处:我们在获取数据的时候,无法使用他的特有行为
//此时推出了泛型,可以在添加哦数据的时候,把类型同意
//而且我们在获取数据的时候,也省得强转了,非常的方便
//1.创建集合的对象
ArrayList list = new ArrayList();
//2.添加数据
// list.add(123);
list.add("aaa");
// list.add(new Student("zhangsan",123));
//3.遍历集合获取里面的每一个元素
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String str = it.next();
//多态的弊端是不能访问子类的特有功能
//obj.length();
//str.length();
System.out.println(str);
}
}
}




泛型类
package org.a04mygenerics;
import java.util.Arrays;
///*
/// 当我在编写一个类的时候,如果不确定类型,那么这个类型可以定义为泛型类
///
/// */
public class MyArrayList<E> {
Object[] obj = new Object[10];
int size;
/*
* E:表示是不确定的类型,改类型在类名后面已经定义过了
* e:形参的名字变量名*/
public boolean add(E e){
obj[size] = e;
size++;
return true;
}
public E get(int index){
return (E) obj[index];
}
@Override
public String toString() {
return Arrays.toString(obj);
}
}
测试类
package org.a04mygenerics;
public class GenricsDemo2 {
public static void main(String[] args) {
/* MyArrayList<String> list = new MyArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
System.out.println(list);*/
MyArrayList<Integer> list2 = new MyArrayList<>();
list2.add(123);
list2.add(456);
list2.add(789);
int i = list2.get(0);
System.out.println(i);
System.out.println(list2);
}
}
泛型方法


泛型类
package org.a04mygenerics;
import java.lang.reflect.Array;
import java.util.ArrayList;
/*
* 定义一个工具类:ListUtil
* 类中定义一个静态方法addALL,用来添加多个集合的元素*/
public class GenricsDemo3 {
public static void main(String[] args) {
ArrayList<String> list1 = new ArrayList<>();
ListUtil.addALL(list1,"aaa","bbb","ccc","ddd");
System.out.println(list1);
ArrayList<Integer> list2 = new ArrayList<>();
ListUtil.addALL(list2,1,2,3,4);
System.out.println(list2);
}
}
测试类
package org.a04mygenerics;
import java.util.ArrayList;
import java.util.Arrays;
public class ListUtil<E> {
private ListUtil(){}
//类中定义一个静态方法addALL,用来添加多个集合的元素
/*
* 参数一:集合
* 参数二~最后:要添加的元素
**/
public static<E> void addALL(ArrayList<E> list,E e1,E e2,E e3,E e4){
list.add(e1);
list.add(e2);
list.add(e3);
list.add(e4);
}
public void show(){
System.out.println("尼古拉斯·纯情·天真·暖女·小香");
}
}
泛型接口

泛型接口的两种使用方法
1.实现类给出具体的类型
2.实现类延续泛型,创建实现类对象时再确定类型
package org.a04mygenerics;
public class GenricsDemo4 {
public static void main(String[] args) {
/*
* 泛型接口的两种使用方式
* 1.实现类给出具体的类型
* 2.实现类延续泛型,创建实现类对象时再确定类型
* */
/* MyArrayList2 list = new MyArrayList2();
list.add("agv");*/
MyArrayList3<String> list = new MyArrayList3();
}
}
1.实现类给出具体的类型
package org.a04mygenerics;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class MyArrayList2 implements List<String> {
@Override
public int size() {
return 0;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public boolean contains(Object o) {
return false;
}
@Override
public Iterator<String> iterator() {
return null;
}
@Override
public Object[] toArray() {
return new Object[0];
}
@Override
public <T> T[] toArray(T[] a) {
return null;
}
@Override
public boolean add(String s) {
return false;
}
@Override
public boolean remove(Object o) {
return false;
}
@Override
public boolean containsAll(Collection<?> c) {
return false;
}
@Override
public boolean addAll(Collection<? extends String> c) {
return false;
}
@Override
public boolean addAll(int index, Collection<? extends String> c) {
return false;
}
@Override
public boolean removeAll(Collection<?> c) {
return false;
}
@Override
public boolean retainAll(Collection<?> c) {
return false;
}
@Override
public void clear() {
}
@Override
public String get(int index) {
return "";
}
@Override
public String set(int index, String element) {
return "";
}
@Override
public void add(int index, String element) {
}
@Override
public String remove(int index) {
return "";
}
@Override
public int indexOf(Object o) {
return 0;
}
@Override
public int lastIndexOf(Object o) {
return 0;
}
@Override
public ListIterator<String> listIterator() {
return null;
}
@Override
public ListIterator<String> listIterator(int index) {
return null;
}
@Override
public List<String> subList(int fromIndex, int toIndex) {
return List.of();
}
}
2.实现类延续泛型,创建实现类对象时再确定类型
package org.a04mygenerics;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class MyArrayList3<E> implements List<E> {
@Override
public int size() {
return 0;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public boolean contains(Object o) {
return false;
}
@Override
public Iterator<E> iterator() {
return null;
}
@Override
public Object[] toArray() {
return new Object[0];
}
@Override
public <T> T[] toArray(T[] a) {
return null;
}
@Override
public boolean add(E e) {
return false;
}
@Override
public boolean remove(Object o) {
return false;
}
@Override
public boolean containsAll(Collection<?> c) {
return false;
}
@Override
public boolean addAll(Collection<? extends E> c) {
return false;
}
@Override
public boolean addAll(int index, Collection<? extends E> c) {
return false;
}
@Override
public boolean removeAll(Collection<?> c) {
return false;
}
@Override
public boolean retainAll(Collection<?> c) {
return false;
}
@Override
public void clear() {
}
@Override
public E get(int index) {
return null;
}
@Override
public E set(int index, E element) {
return null;
}
@Override
public void add(int index, E element) {
}
@Override
public E remove(int index) {
return null;
}
@Override
public int indexOf(Object o) {
return 0;
}
@Override
public int lastIndexOf(Object o) {
return 0;
}
@Override
public ListIterator<E> listIterator() {
return null;
}
@Override
public ListIterator<E> listIterator(int index) {
return null;
}
@Override
public List<E> subList(int fromIndex, int toIndex) {
return List.of();
}
}
泛型的继承和通配符
泛型的通配符
?也表示不确定的类型
他可以进行类型的限定
? extends E : 表示可以传递E或者E所有的子类类型
? extends E : 表示可以传递E或者E所有父类类型
? super E: 表示可以传递E或者E所有父类类型
应用场景:
们在定有类/方法/接口的时候,如果类型不确定,就可以定义泛型类/泛型方法/泛型接口。
如果类型不确定,但是我现在能知道以后只能产地的继承体系中的,就可以泛型的通配符
关键点:可以限定类型的范围。
案例

泛型总结


数据结构(树)







左旋







红黑树




Set

HashSet







LinkedHashSet

TreeSet


总结
- 如果想要集合中的 元素可重复:使用ArrayList集合,基于数组
- 如果想要集合中的元素可重复,而且当前的增删操作明显多于查询:使用LinkedList集合,基于链表
- 如果想要集合中的元素去重:使用HashSet集合,基于哈希表
- 如果想要集合中的元素去重而且保证存取顺序:使用LinkedHashSet集合,基于哈希表和双链表。效率低于HashSet
- 如果想要集合中的元素进行排序:使用TreeSet集合,基于红黑树,后续也可以用List集合实现排序
双列集合
一一对应,键值对
特点
- 双列集合一次需要存一对数据,分别为键和值
- 键不能重复,值可以重复
- 键和值是一一对应的,每一个键只能找到自己对应的值
- 键+值这个整体,我们称之为“键值”或者“键值对对象”,在Java中叫做“Entry对象”
Map中常见的API
Map是双列集合的顶层接口,他的功能是全部双列集合都可以继承使用的
- V put(K Key ,V value) 添加元素
- V remove(Object key) 根据键删除键值对元素
- void clear() 移除所有的键值对元素
- boolean containsKey(Object key) 判断集合是否包含指定的键
- boolean containsValue(Object value) 判断集合是否包含指定的值
- boolean isEmpty() 判断集合是否为空
- int size() 集合的长度,也就是集合中键值对的个数
Map中的遍历方式
- 键找值
- 键值对
- Lambda表达式
1.键找值
获取所有的键,把这些键放到一个单列集合中
Set<String> keys = map.MapSet();
遍历集合,得到每一个键
for(String key : keys){
//0.2System.out.println(key);
//利用map集合中的键去获得相应的值
String value = map.get(key);
System.out.println(key + "=" + value);
}
2.键值对
通过一个方法获取所有的键值对对象,返回一个Set集合
Set<Map.Entry<String,String>> entries = map.entrySet();
遍历entries这个集合,去得到里面的每一个键值对象
for (Map.Entry<String,String>entry : entries){
//利用entry调用get方法获取键和值
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key + "=" + value);
}
3.Lambda表达式
利用lambda表达式进行遍历
底层:
forEach其实就是利用第二种方法进行遍历,依次得到每一个键和值
再调用accept方法
map.forEach(new BiConsumer<Stirng,Stirng>(){
@Override
public void accept(String key,String value){
System.out.println(key + "=" +value);
}
})
System.out.println("-------");
map.forEach((String key,String value)->{
System.out.println(key + "=" +value);
}
);
System.out.println("-------");
map.forEach((key,value)->
System.out.println(key + "=" +value));
HashMap的特点


package org.MapTest;
import java.util.*;
public class attraction {
public static void main(String[] args) {
//1.需要先让同学们投票
//定义一个数组 储存4个景点
String[] arr = {"A","B","C","D"};
//利用随机树模拟80个同学的投票,并把投票结果存储起来
ArrayList<String> list = new ArrayList<>();
Random r = new Random();
for (int i = 0; i < 80; i++) {
int index = r.nextInt(arr.length);
list.add(arr[index]);
}
//2.如果要统计的东西比较多,不方便使用计数器思想
//我们可以定义MAp集合,利用集合进行统计
HashMap<String,Integer> hm = new HashMap<>();
for (String name : list) {
//判断当前的景点再map集合中是否存在
if(hm.containsKey(name)){
//存在
//先获取当前景点已经被投票的次数
int count = hm.get(name);
//表示当前景点又被投了一次
count++;
//把新的次数再次添加到集合当中
hm.put(name,count);
}else {
//不存在
hm.put(name,1);
}
}
System.out.println(hm);
//3.求最大值
//A ???
//B ???
//C ???
//D ???
int max = 0;
Set<Map.Entry<String, Integer>> entries = hm.entrySet();
for (Map.Entry<String, Integer> entry : entries) {
int count = entry.getValue();
if(count > max){
max = count;
}
}
System.out.println(max);
//遍历
//4.判断那个景点的次数跟最大值一样,如果一样,打印出来.
for (Map.Entry<String, Integer> entry : entries) {
int count = entry.getValue();
if(count == max){
System.out.println(entry.getKey());
}
}
}
}
LinkedHashMap

TreeMap

默认情况下按照键的升序进行排序
这是降序:

可变参数
求n个数据的和
原来的
现在的可变参数

可变参数的小细节:
- 在方法的形参中最多只能写一个可变参数

Collections工具

集合的批量添加


练习
一


浙公网安备 33010602011771号