2020/8/13
1.Collection
1.1 集合概述
-
集合的作用
- 集合是一种容器,用来存储引用数据类型.
-
集合的特点
- 只能存储引用数据类型,不能存储基本类型,如果要存基本类型对应的包装类。
- 集合长度可变
-
单列集合的体系
1.2 Collection常用方法
-
public boolean add(E e) : 把给定的对象添加到当前集合中 。返回始终是true
-
public void clear() :清空集合中所有的元素。(不咋用)
-
public boolean remove(E e) : 把给定的对象在当前集合中删除。如果有多个删除第一个。
-
public boolean contains(Object obj) : 判断当前集合中是否包含给定的对象。
-
public boolean isEmpty() : 判断当前集合是否为空。(不咋用)
-
public int size() : 返回集合中元素的个数。
-
public Object[] toArray() : 把集合中的元素,存储到数组中。(不咋用)
-
实例代码
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 迭代器的问题:并发修改异常
-
异常
- ConcurrentModificationExceptionC
-
产生原因
- 在迭代器遍历集合的时候,如果使用集合对象增删集合元素,就会出现并发修改异常。
-
解决办法:
-
如果要删除元素,可以使用迭代器的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 数组
- 可以去存储多个数据,在内存中开辟了一段连续的空间。
- 元素查询快
- 元素增删慢
4.4 链表
- 链表可以存储多个数据,在内存中开辟的是不连续的空间。
- 元素查询慢
- 元素增槎快
4.5 树
-
树的介绍
- 每一个节点有零个或者多个子节点
- 没有父节点的节点称之为根节点,一个树最多有一个根节点。
- 每一个非根节点有且只有一个父节点
-
二叉树
-
如果树中的每个节点的子节点的个数不超过2,那么该树就是一个二叉树。
-
二叉查找树
- 左子树上所有的节点的值均小于它的根节点的值
- 右子树上所有的节点值均大于它的根节点的值
- 每一个子节点最多有两个子树
- 二叉寻找树的遍历
- 左中右的方式
- 左中右的方式
-
平衡二叉树的红黑树
5.List接口
5.1 List的特点
- 元素有索引
- 元素可重复
- 元素存取有序
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.4 Arraylist集合
-
介绍
- ArrayList是集合体系中最常用的集合。
- ArrayList的底层是数组结构。
- 元素查询快
- 元素增删慢
5.5 LinkedList集合
-
介绍
- LinkedList底层是由双向链表实现。
- 元素查询慢
- 元素增删快
- LinkedList底层是由双向链表实现。
-
特有方法
方法 说明 void addFirst(E e) 往开头添加元素 void addLast(E e) 往末尾添加元素 E getFirst() 获取开头的元素 E getLast() 获取末尾的元素 E removeFirst() 删除开头的元素 E removeLast() 删除末尾的元素 E pop() 模拟栈的结构,弹出一个元素 void push(E e) 模拟栈的结构,推入一个元素 -
LinkedList的add方法源码解析
![LinkedList的源码](E:/Feiq/Recv%20Files/day05/%E7%AC%94%E8%AE%B0/img/LinkedList%E7%9A%84%E6%BA%90%E7%A0%81.png)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.简单的斗地主发牌案例
import java.util.ArrayList;
import java.util.Collections;
public class Test6_1 {
public static void main(String[] args) {
ArrayList<String> poker = new ArrayList<>();
String[] color = {"♦", "♥", "♠", "♣"};
String[] number = {"2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K","A"};
for (int i = 0; i < color.length; i++) {
for (int j = 0; j < number.length; j++) {
poker.add(color[i] + number[j]);
}
}
/* for (String s : color) {
for (String s1 : number) {
poker.add(s+s1);
}
}*/
poker.add("大王");
poker.add("小王");
Collections.shuffle(poker);
ArrayList<String> gaochao = new ArrayList<>();
ArrayList<String> gaoshaoxu = new ArrayList<>();
ArrayList<String> fzs = new ArrayList<>();
ArrayList<String> dipai = new ArrayList<>();
for (int i = 0; i < poker.size(); i++) {
String s = poker.get(i);
if (i >= 51) {
dipai.add(s);
} else if (i % 3 == 0) {
gaochao.add(s);
} else if (i % 3 == 1) {
gaoshaoxu.add(s);
} else {
fzs.add(s);
}
}
System.out.println(gaochao);
System.out.println(gaoshaoxu);
System.out.println(fzs);
System.out.println(dipai);
}
}