1.Collection
1.1集合概述
-
集合的作用:
- 集合是一种容器,用来存储引用数据类型。
-
集合的特点:
- 只能存储引用类型,不能存储基本类型,如果要存基本类型存对应的包装类
- 集合的长度可变。
-
单列集合的体系:
1.2Collection常用方法【重点】
方法 | 说明 |
---|---|
boolean add(E e) | 添加方法 |
void clear()[不用] | 清空集合中的元素 |
boolean remove(Object e) | 删除集合中的某个元素 |
boolean contains(Object obj) | 判断集合是否包含某个元素 |
boolean isEmpty()[不用] | 判断集合是否为空 |
int size() | 获取集合的长度 |
Object[] toArray()[不用] | 把集合转成Object[]类型 |
-
示例代码:
import java.util.ArrayList; import java.util.Collection; public class Test01 { public static void main(String[] args) { //创建对象 Collection<String> coll = new ArrayList<>(); //boolean add(E e) :添加方法 coll.add("柳岩"); coll.add("石原里美"); coll.add("王先生"); coll.add("石原里美"); //void clear() :清空集合的元素 //coll.clear(); //boolean remove(Object e) :删除指定的元素,如果有多个删除第一个 coll.remove("石原里美"); //boolean contains(Object obj) :判断是否包含某个元素 boolean b = coll.contains("石原"); System.out.println(b); //int size() :获取集合的长度 int size = coll.size(); System.out.println(size); //boolean isEmpty() :判断集合是否为空 boolean b2 = coll.isEmpty(); System.out.println(b2); //Object[] toArray() :把集合转成Object[]数组 Object[] arr = coll.toArray(); //打印 System.out.println(coll); } }
2.Iterator迭代器【重点】
2.1迭代器的作用
迭代器是帮助集合做遍历的类。
2.2迭代器如何获取
Collection集合有这个方法:
方法 | 说明 |
---|---|
Iterator iterator() | 获取迭代器对象 |
2.3迭代器常用方法
- Iterator接口常用的有两个方法:
方法 | 说明 |
---|---|
E next() | 获取集合中的元素 |
boolean hasNext() | 判断集合中有没有下一个元素 |
void remove() | 删除当前元素 |
- 示例代码:
public class Test02 {
public static void main(String[] args) {
//创建对象
Collection<String> coll = new ArrayList<>();
//boolean add(E e) :添加方法
coll.add("柳岩");
coll.add("石原里美");
coll.add("王先生");
coll.add("石原里美");
//遍历集合
//获取迭代器对象
//hasNext() 判断有没有下一个元素
//next() 获取当前元素
Iterator<String> it = coll.iterator();
//循环
//快捷键:itit
while(it.hasNext()){
String s = it.next();
System.out.println(s);
}
}
}
2.4迭代器原理
-
源码
public boolean hasNext() { return cursor != size; } public E next() { checkForComodification(); int i = cursor; if (i >= size){ throw new NoSuchElementException(); } Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length){ throw new ConcurrentModificationException(); } cursor = i + 1; return (E) elementData[lastRet = i]; }
2.5迭代器的问题:并发修改异常
-
异常:
ConcurrentModificationException
-
产生原因:
- 在迭代器遍历集合的时候,如果使用集合对象增删集合元素,就会出现并发修改异常。
-
代码演示:
public class Test02 { public static void main(String[] args) { //创建对象 Collection<String> coll = new ArrayList<>(); //boolean add(E e) :添加方法 coll.add("柳岩"); coll.add("石原里美"); coll.add("王先生"); coll.add("石原里美"); //遍历集合 //获取迭代器对象 //hasNext() 判断有没有下一个元素 //next() 获取当前元素 Iterator<String> it = coll.iterator(); //循环 while(it.hasNext()){ //集合删除 coll.remove("柳岩"); String s = it.next(); System.out.println(s); } } }
-
解决办法:
- 如果要删除元素,可以使用迭代器的remove()方法
- 如果要添加元素,迭代器里面没有提供添加的方法。如果要用需要使用另一个迭代器ListItr
//删除演示: Iterator<String> it = coll.iterator(); //循环 //快捷键:itit while (it.hasNext()) { String s = it.next(); //判断之后删除 if(s.equals("柳岩")){ it.remove(); //删除当前元素 } }
2.6增强for循环【重点】
-
作用
- 遍历集合获取每个元素
-
格式
for(元素类型 元素名 : 集合/数组){ 代码; }
-
代码演示
public class Test03 { public static void main(String[] args) { //创建对象 Collection<String> coll = new ArrayList<>(); //boolean add(E e) :添加方法 coll.add("柳岩"); coll.add("石原里美"); coll.add("王先生"); coll.add("石原里美"); //遍历集合 /* for(元素类型 元素名 : 集合/数组){ 代码; } */ //快捷键:集合.for //快捷键:iter for(String s : coll){ System.out.println(s); } } }
-
增强for的本质
- 增强for其实底层也是用迭代器来实现的,增强for也会出现并发修改异常
3.泛型【了解即可】
3.1泛型的作用
泛型是指代某种引用数据类型,在定义的时候通常一个大写字母来表示,在使用的时候去确定具体的类型。
泛型可以定义在类上,方法上,和接口上。
学习泛型的定义我们并不会去写,学习它的目的是让你能理解java底层的设计原理。
3.2类上定义泛型
-
类上定义泛型格式:
public class 类名<E>{ }
-
何时确定类型:
- 在创建对象时确定具体的数据类型
-
代码演示:
public class Student<E> { //姓名 String name; //年龄 int age; //泛型来代表某一种引用类型 E aaa; //set get public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public E getAaa() { return aaa; } public void setAaa(E aaa) { this.aaa = aaa; } } public class Test01 { public static void main(String[] args) { //创建对象 Student<Integer> s = new Student<>(); s.setName("柳岩"); s.setAge(28); s.setAaa(123); //创建对象 Student<String> s2 = new Student<>(); s2.setName("柳岩"); s2.setAge(28); s2.setAaa("abc"); } }
3.3方法上定义泛型
-
方法上定义泛型格式:
public <E> void method(){ }
-
何时确定类型:
- 在调用方法的时候确定具体的类型。
-
代码演示:
public class Person { //泛型方法 public <E> void method(E e){ } } public class Test02 { public static void main(String[] args) { //创建对象 Person p = new Person(); //调用方法 //对于这个方法E就是字符串 p.method("123"); //对于这个方法E就是整数 p.method(123); //演示泛型方法的使用 Collection<String> coll = new ArrayList<>(); //给集合添加多个元素(这是一个泛型方法) Collections.addAll(coll,"柳岩","刘艳"); //打印 System.out.println(coll); } }
3.4接口上定义泛型
-
接口上定义泛型格式:
public interface 接口名<E>{ }
-
何时确认类型:
- 方式一:在实现类中确定具体的数据类型
- 方式二:在实现类中不确定类型,在创建对象时再确定具体的类型
public interface AAA<E> { //抽象方法 void add(E e); } //方式一: //对于这个实现类泛型就是String public class BBB implements AAA<String> { @Override public void add(String s) { } } //方式二: //把接口的泛型变成类的泛型 public class CCC<E> implements AAA<E> { @Override public void add(E e) { } } public class Test03 { public static void main(String[] args) { //创建对象 CCC<String> c = new CCC<>(); c.add("abc"); //创建对象 CCC<Double> c2 = new CCC<>(); c2.add(3.13); } }
3.5泛型通配符【重要】
-
格式:
<?> :可以代表任何泛型类型 * <? extends X> :可以代表X以及X的子类类型(泛型的上限) * <? super X> :可以代表X以及X的父类类型(泛型的下限)
-
示例代码:
import java.util.ArrayList; public class Test04 { public static void main(String[] args) { ArrayList<Dog> list1 = new ArrayList<>(); ArrayList<String> list2 = new ArrayList<>(); ArrayList<Cat> list3 = new ArrayList<>(); ArrayList<Animal> list4 = new ArrayList<>(); //调用方法 method(list4); } //演示泛型通配符 //这样不能传入 ArrayList<Dog>,因为泛型没有多态 //public static void method(ArrayList<Animal> list){ //代表可以接受任意泛型类型 //public static void method(ArrayList<?> list){ //代表接受Animal和Animal的子类类型 //public static void method(ArrayList<? extends Animal> list){ //代表接受Cat和Cat的父类类型 public static void method(ArrayList<? super Cat> list){ } }
4.数据结构【重点】
4.1栈和队列
栈:
它只能在一个结构的一个固定端进行数据结点的插入和删除操作。
队列:
它在一个结构的两个固定端进行数据结点的插入和删除操作。
4.2数组和链表
数组:
数组可以存储多个数据,在内存中开辟了一段连续的空间。
链表:
链表可以存储多个数据,在内存中开辟的是不连续的空间。
4.3树:
-
树的介绍
- 每一个节点有零个或者多个子节点
- 没有父节点的节点称之为根节点,一个树最多有一个根节点。
- 每一个非根节点有且只有一个父节点
-
二叉树
- 如果树中的每个节点的子节点的个数不超过2,那么该树就是一个二叉树。
-
二叉查找树
-
左子树上所有的节点的值均小于它的根节点的值
-
右子树上所有的节点值均大于它的根节点的值
-
每一个子节点最多有两个子树
-
-
二叉查找树的遍历
- 左中右的方式遍历
-
平衡二叉树和红黑树
5 .List接口【重点】
5.1List的特点
- 元素有索引
- 元素可重复
- 元素存取有序
5.2常用方法
方法 | 说明 |
---|---|
void add(int index, E element) | 在指定的索引添加元素 |
E get(int index) | 获取指定索引处的元素 |
E remove(int index) | 删除指定索引处的元素 |
E set(int index, E element) | 修改指定索引处的元素 |
5.3代码演示
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Test01 {
public static void main(String[] args) {
//创建集合对象
List<String> list = new ArrayList<>();
list.add("柳岩");
list.add("王先生");
//void add(int index, E element)
//在指定的索引添加元素
list.add(1,"张师傅");
//E get(int index)
//获取指定索引处的元素
String s = list.get(0);
System.out.println(s); //柳岩
//E remove(int index)
//删除指定索引处的元素
list.remove(2);
//E set(int index, E element)
//修改指定索引处的元素
list.set(0,"凤儿");
//List集合的遍历
//迭代器
Iterator<String> it = list.iterator();
while (it.hasNext()) {
String str = it.next();
System.out.println(str);
}
//增强for
for (String str : list) {
System.out.println(str);
}
//普通for
for (int i = 0; i < list.size(); i++) {
String str = list.get(i);
System.out.println(str);
}
}
}
5.4ArrayList集合
-
介绍
- ArrayList是集合体系中最常用的集合。
- ArrayList的底层是数组结构。
- 元素查询快
- 元素增删慢
//ArrayList没有自己的特殊方法,用的都是父类中定义的方法 import java.util.ArrayList; public class Test02 { public static void main(String[] args) { //创建对象 ArrayList<String> list = new ArrayList<>(); //添加元素 list.add("柳岩"); list.add("王先生"); list.add("王先生"); list.add(1,"张师傅"); System.out.println(list); } }
5.5LinkedList集合【了解即可】
- 介绍
- LinkedList底层是由双向链表实现。
- 元素查询慢
- 元素增删快
- LinkedList底层是由双向链表实现。
- 特有方法
方法 | 说明 |
---|---|
void addFirst(E e) | 往开头添加元素 |
void addLast(E e) | 往末尾添加元素 |
E getFirst() | 获取开头的元素 |
E getLast() | 获取末尾的元素 |
E removeFirst() | 删除开头的元素 |
E removeLast() | 删除末尾的元素 |
E pop() | 模拟栈的结构,弹出一个元素 |
void push(E e) | 模拟栈的结构,推入一个元素 |
- 代码演示
public class Test03 {
public static void main(String[] args) {
//创建对象
LinkedList<String> list = new LinkedList<>();
//添加元素
list.add("柳岩");
list.add("王先生");
//void addFirst(E e)
//往开头添加元素
list.addFirst("张三");
//void addLast(E e)
//往末尾添加元素
list.addLast("赵四");
//其他方法也没有使用价值所以不用
System.out.println(list); //
}
}
-
LinkedList的add方法源码解析
private static class Node<E> { E item; Node<E> next; Node<E> prev; Node(Node<E> prev, E element, Node<E> next) { this.item = element; this.next = next; this.prev = prev; } } void linkLast(E e) { final Node<E> l = last; final Node<E> newNode = new Node<>(l, e, null); last = newNode; if (l == null) first = newNode; else l.next = newNode; size++; modCount++; }
6.案例(简单的斗地主发牌案例)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zoR3vRvr-1597769926521)(img\斗地主分析.png)]
import java.util.ArrayList;
import java.util.Collections;
public class Test01 {
public static void main(String[] args) {
//创建集合
ArrayList<String> poker = new ArrayList<>();
//数组表示花色
String[] color = {"♦","♥","♣","♠"};
//数组表示数字
String[] num = {"2","3","4","5","6","7","8","9","10","J","Q","K","A"};
//循环遍历花色
for (String c : color) {
//循环遍历数字
for (String n : num) {
//添加到集合中
poker.add(c+n);
}
}
//存放大小王
poker.add("小王");
poker.add("大王");
//洗牌
Collections.shuffle(poker);
//创建4个集合
ArrayList<String> list1 = new ArrayList<>();
ArrayList<String> list2 = new ArrayList<>();
ArrayList<String> list3 = new ArrayList<>();
ArrayList<String> list4 = new ArrayList<>();
//发牌(普通for遍历有索引)
for (int i = 0; i < poker.size(); i++) {
String pai = poker.get(i);
if(i >= 51){
list4.add(pai);
}else if(i%3==0){
list1.add(pai);
}else if(i%3==1){
list2.add(pai);
}else{
list3.add(pai);
}
}
//看牌
System.out.println("柳岩 :" + list1);
System.out.println("卢本伟:" + list2);
System.out.println("阿姨 :" + list3);
System.out.println("底牌 :" + list4);
}
}