day16
一、数据结构
数据结构:实际上就是存储数据和展示数据的方式。合理的选择数据结构解决问题,可以获得比之前更高的运行效率。
常见的数据结构有:栈和队列、数组和链表
1.1 栈和队列
栈
栈,stack。是一个受限的线性表。这个受限体现在存储和删除数据的时候都只能在一端操作。其它任何位置都不能进行存储和删除等操作。
特点:
1. 只能在一端进行访问(也就是出口和入口是一个位置)
2. 先进后出
![栈](img/栈.gif)
队列
队列,Queue。是一种受限的线性表。这个受限体现在只能在一端进入,在另一端出。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yeX3wVOt-1620344821401)(img/image-20210426101844694.png)]
1.2 数组和链表
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5Uq1KE2w-1620344821403)(img/image-20210426104419466.png)]
二、List的常见子类
ArrayList
LinkedList
2.1 ArrayList
底层是数组:查找快、增删慢
可以存储null值
不同步(不加锁),效率高
构造方法
ArrayList() 构造一个初始容量为 10 的空列表
扩容方式【记住结论】
ArrayList的容量一旦不够用了,就会进行扩容。扩容的大小为原来数组的1.5倍。
int newCapacity = oldCapacity + (oldCapacity >> 1);
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NknjjnfO-1620344821405)(img/image-20210426140539044.png)]
练习:
1. 创建一个ArrayList集合,存储3个字符串,并通过迭代器遍历
2. 创建一个ArrayList集合,存储3个Person对象,并通过迭代器遍历
使用集合的步骤 【掌握】
1. 创建集合对象
2. 创建元素对象
3. 将元素对象添加到集合对象中
4. 通过迭代器遍历
1. 通过集合对象调用iterator方法获取迭代器对象
2. 通过迭代器对象调用hasNext方法判断是否还有元素可以被迭代
3. 通过迭代器对象调用next方法获取元素
public class Demo6 {
public static void main(String[] args) {
//1. 创建集合对象
ArrayList al = new ArrayList();
//2. 创建元素对象
Person p = new Person("zhangsan", 33);
Person p2 = new Person("lisi", 44);
Person p3 = new Person("wangwu", 55);
//3. 将元素对象添加到集合对象中
al.add(p);
al.add(p2);
al.add(p3);
//4. 通过迭代器遍历
//4.1 通过集合对象调用iterator方法获取迭代器对象
Iterator it = al.iterator();
//4.2 通过迭代器对象调用hasNext方法判断是否还有元素可以被迭代
while(it.hasNext()){
//4.3 通过迭代器对象调用next方法获取元素
Person next = (Person) it.next();
System.out.println(next);
}
}
}
2.2 LinkedList
底层是链表:查找慢、增删快
可以存储null值
不同步(不加锁),效率高
构造方法
LinkedList() 构造一个空列表
public class Demo {
public static void main(String[] args) {
//LinkedList() 构造一个空列表
LinkedList ll = new LinkedList();
ll.add("A");
ll.add("B");
ll.add("C");
Iterator it = ll.iterator();
while(it.hasNext()){
String next = (String) it.next();
System.out.println(next);
}
}
}
特有方法
void addFirst(E e) 将指定元素插入此列表的开头
void addLast(E e) 将指定元素添加到此列表的结尾
E getFirst() 返回此列表的第一个元素
E getLast() 返回此列表的最后一个元素
E removeFirst() 移除并返回此列表的第一个元素
E removeLast() 移除并返回此列表的最后一个元素
public class Demo2 {
public static void main(String[] args) {
LinkedList ll = new LinkedList();
ll.add("Hello");
ll.add("World");
ll.add("Java");
System.out.println(ll); //[Hello, World, Java]
//void addFirst(E e) 将指定元素插入此列表的开头
// ll.addFirst("Japan");
// System.out.println(ll); //[Japan, Hello, World, Java]
// ll.addFirst("England");
// System.out.println(ll); //[England, Japan, Hello, World, Java]
//void addLast(E e) 将指定元素添加到此列表的结尾
// ll.addLast("Japan");
// System.out.println(ll); //[Hello, World, Java, Japan]
//E getFirst() 返回此列表的第一个元素
// System.out.println(ll.getFirst()); //Hello
//E getLast() 返回此列表的最后一个元素
// System.out.println(ll.getLast()); //Java
//E removeFirst() 移除并返回此列表的第一个元素
// Object o = ll.removeFirst();
// System.out.println("被移除的元素为:" + o);
// System.out.println(ll);
//E removeLast() 移除并返回此列表的最后一个元素
Object o = ll.removeLast();
System.out.println("被移除的元素为:" + o); // 被移除的元素为:Java
System.out.println(ll); // [Hello, World]
}
}
源码分析 【理解】
参考另一个笔记 【LinkedList源码分析.pdf】
2.3 如何选择List的子类
如果查询比较多,那么就使用 ArrayList
如果增删比较多,那么就使用 LinkedList
三、泛型 【会用】
泛型:就是一种参数化的类型。比如定义一个类的时候,类中的方法的参数或者返回值我们还不确定。那我们可以先用一个符号代替。这个符号就是泛型。
具体这个泛型(也就是符号)代替什么类型,那必须要等到我们使用的时候才能明确。
3.1 简单使用
不使用泛型
import java.util.ArrayList;
import java.util.Iterator;
public class Demo {
public static void main(String[] args) {
//不使用泛型
ArrayList al = new ArrayList();
al.add("Hello");
al.add(666);
al.add('中');
Iterator it = al.iterator();
while(it.hasNext()){
String s = (String)it.next(); //类型转换异常
System.out.println(s);
}
}
}
使用泛型 【掌握】
import java.util.ArrayList;
import java.util.Iterator;
public class Demo {
public static void main(String[] args) {
//使用泛型
ArrayList<String> list = new ArrayList<String>();
list.add("Hello");
// list.add(666); //编译报错
// list.add('中'); //编译报错
list.add("666");
list.add("中");
Iterator<String> itt = list.iterator();
while(itt.hasNext()){
String next = itt.next();
System.out.println(next);
}
}
}
3.2 好处
1. 能将运行时期的问题,提前到了编译期
2. 省去了类型强转的麻烦
3.3 泛型的推断
如果已经通过数据类型确定好泛型之后,那么后面的<>中就可以不用再放具体的数据类型了(也就是留空即可) jdk1.7出来的内容
public class Demo2 {
public static void main(String[] args) {
ArrayList<String> al = new ArrayList<>();
al.add("Hello");
al.add("Hello2");
al.add("Hello3");
Iterator<String> it = al.iterator();
while(it.hasNext()){
String s = it.next();
System.out.println(s);
}
}
}
3.4 泛型类
格式:
class 类名 <泛型1, 泛型2, ...> {
}
注意:
1. 泛型必须为引用数据类型
2. 一个类可以同时在<>中声明多个泛型,中间用英文状态的逗号分隔开就行
3. 泛型命名的时候只要符合标识符的命名规范即可,一般都用如下字母: K V T E
4. 泛型只是一种参数化的类型,一旦在类上声明之后,就可以当成确定的类型在类中使用了。
public class DynamicArray <E> {
private Object[] arr;
private int size;
public DynamicArray(){
arr = new Object[10];
}
//添加方法
public void add(E e){
arr[size++] = e;
}
}
public class Demo3 {
public static void main(String[] args) {
// DynamicArray<String> da = new DynamicArray<>();
// da.add("Hello");
DynamicArray<Integer> da = new DynamicArray<>();
da.add(666);
}
}
3.5 泛型方法
格式:
修饰符 <泛型1, 泛型2, ...> 返回值类型 方法名(参数列表) {
}
注意:
1. 泛型方法中定义的泛型只能在本方法中使用,其它方法不能使用
public class DD {
public <坤坤> void test(坤坤 kk){
System.out.println("Hello:" + kk);
}
}
public class Demo4 {
public static void main(String[] args) {
DD d = new DD();
d.<String>test("Java");
d.<Integer>test(666);
}
}
3.6 泛型的通配符
如果你不知道要使用什么泛型,那么就直接使用?即可。 ?就代表了所有的泛型
? 代表了所有的泛型
? extends E 代表了E类型,及其E类型所有的子类
? super E 代表了E类型,及其E类型所有的父类
package com.ujiuye.demo03_泛型;
import java.util.ArrayList;
class Animal { }
class Dog extends Animal {}
class Cat extends Animal {}
class CoffeeCat extends Cat {}
public class Demo5 {
public static void main(String[] args) {
//? 代表了所有的泛型
// ArrayList<?> al = new ArrayList<Animal>();
// ArrayList<?> al2 = new ArrayList<Dog>();
// ArrayList<?> al3 = new ArrayList<Cat>();
// ArrayList<?> al4 = new ArrayList<CoffeeCat>();
//? extends E 代表了E类型,及其E类型所有的子类
// ArrayList<? extends Cat> al = new ArrayList<Animal>(); //编译报错
// ArrayList<? extends Cat> al2 = new ArrayList<Dog>(); //编译报错
// ArrayList<? extends Cat> al3 = new ArrayList<Cat>();
// ArrayList<? extends Cat> al4 = new ArrayList<CoffeeCat>();
//? super E 代表了E类型,及其E类型所有的父类
// ArrayList<? super Cat> al = new ArrayList<Animal>();
// ArrayList<? super Cat> al2 = new ArrayList<Dog>(); //编译报错
// ArrayList<? super Cat> al3 = new ArrayList<Cat>();
// ArrayList<? super Cat> al4 = new ArrayList<CoffeeCat>(); //编译报错
}
}
四、Set
一个不包含重复元素的 collection。
Set不保证元素的有序性。
没有索引
4.1 获取Set对象的方式
通过其实现类创建对象
Set<String> set = new HashSet<>();
import java.util.HashSet;
import java.util.Set;
public class Demo {
public static void main(String[] args) {
//1. 创建Set集合的对象
Set<String> set = new HashSet<>();
//2. 将元素对象添加到集合中
set.add("hello");
set.add("java");
set.add("world");
set.add("java");
//3. 输出
System.out.println(set); //[java, world, hello] 无序
System.out.println("-------------------");
Set<Character> set2 = new HashSet<>();
set2.add('A');
set2.add('Z');
set2.add('C');
System.out.println(set2); //[A, C, Z] 有序
}
}
4.2 遍历Set的方式
1. toArray
2. toArray(T[] a)
3. iterator
4. 增强for
package com.ujiuye.demo04_Set接口;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class Demo2 {
public static void main(String[] args) {
Set<String> set = new HashSet<>();
set.add("hello");
set.add("world");
set.add("java");
//1. toArray
// Object[] objects = set.toArray();
// for(int i = 0; i < objects.length; i++){
//
// System.out.println(objects[i]);
// }
//2. toArray(T[] a)
//先按照结果的类型创建一个数组,用来存储结果
// String[] s = new String[set.size()];
// String[] ss = set.toArray(s);
// for(int i = 0; i < ss.length; i++){
//
// System.out.println(ss[i]);
// }
//3. iterator
//while中使用iterator 【目前建议使用】
// Iterator<String> it = set.iterator();
// while(it.hasNext()){
// String next = it.next();
// System.out.println(next);
// }
//for中使用iterator 【开发中建议使用】
// for(Iterator<String> it = set.iterator(); it.hasNext();){
//
// String next = it.next();
// System.out.println(next);
// }
//4. 增强for
// for(String s : set){
//
// System.out.println(s);
// }
//输出集合
System.out.println(set.toString());
}
}
ng> it = set.iterator();
// while(it.hasNext()){
// String next = it.next();
// System.out.println(next);
// }
//for中使用iterator 【开发中建议使用】
// for(Iterator it = set.iterator(); it.hasNext()😉{
//
// String next = it.next();
// System.out.println(next);
// }
//4. 增强for
// for(String s : set){
//
// System.out.println(s);
// }
//输出集合
System.out.println(set.toString());
}
}