集合:
Collection(I) + Map(I)
Collection(I):
|- List(I) - 顺序结构
|- ArrayList© - 数组
|- LinkedList© - 链表
|- Vector© - 数组
|- Set(I) - 散列结构 -> Map(I)
|- SortedSet(I)
|- TreeSet©
|- hashSet©
|- Queue(I) - 队列
|- Dueque(I)
|-LinkedList©
List集合 - 顺序结构
1.List集合的特点
a.List集合是顺序结构,所以是有序列表,可以是用index
b.List集合允许有重复值
c.List集合允许有null值
2.特有方法(带有index)
add(int index, E element)
addAll(int index, Collection<? extends E> c)
set(int index, E element)
subList(int fromIndex, int toIndex)
remove(int index)
get(int index)
3.实现类
ArrayList©
底层实现:数组
底层数据结构:数组
特点:
优点: 查询速度很快(因为有连续的下标,可以根据下标进行查询)
缺点:
a.插入/删除很慢的
b.顺序结构需要连续的物理空间
导致空间的使用率非常低
package api05.Collection.list;
import java.util.ArrayList;
import java.util.List;
/*
List集合
*/
public class ListDemo01 {
public static void main(String[] args) {
List list = new ArrayList();
list.add("1");
list.add("1");
list.add("2");
list.add("4");
System.out.println(list);
//subList
//前包含后不包含
List sub = list.subList(0, 2);
System.out.println(sub);
//sub新集合
sub.add("张三");
System.out.println(sub);
//原集合有没有包含 张三
//[1, 1, 张三, 2, 4]
//原集合 和 子集合共用同一块内存空间
System.out.println(list);
}
}
package api05.Collection.list;
import java.util.ArrayList;
import java.util.LinkedList;
/*
ArrayList和LinkedList的效率对比
*/
public class ListDemo02 {
public static void main(String[] args) {
ArrayList arr = new ArrayList();
LinkedList linked = new LinkedList<>();
for (int i = 0; i < 5000000; i++) {
arr.add("i" + i);
linked.add("i"+i );
}
//查询 - ArrayList
/* long time1 = System.currentTimeMillis();
arr.get(0);
long time2 = System.currentTimeMillis();
linked.get(0);
long time3 = System.currentTimeMillis();
System.out.println("arr查询效率:" + (time2 - time1));
System.out.println("linked查询效率:" + (time3 - time2));
//从中间查
long time4 = System.currentTimeMillis();
arr.get(2500000);
long time5 = System.currentTimeMillis();
linked.get(2500000);
long time6 = System.currentTimeMillis();
System.out.println("arr查询效率:" + (time5 - time4));
System.out.println("linked查询效率:" + (time6 - time5));
//从尾部查询
long time7 = System.currentTimeMillis();
arr.get(4999999);
long time8 = System.currentTimeMillis();
linked.get(4999999);
long time9 = System.currentTimeMillis();
System.out.println("arr查询效率:" + (time8 - time7));
System.out.println("linked查询效率:" + (time9 - time8));
*/
//插入 - LinkedList快
long time1 = System.currentTimeMillis();
arr.add(0,"1");
long time2 = System.currentTimeMillis();
linked.add(0,"1");
long time3 = System.currentTimeMillis();
System.out.println("arr查询效率:" + (time2 - time1));
System.out.println("linked查询效率:" + (time3 - time2));
//从中间查
long time4 = System.currentTimeMillis();
arr.add(2500000,"1");
long time5 = System.currentTimeMillis();
linked.add(2500000,"1");
long time6 = System.currentTimeMillis();
System.out.println("arr查询效率:" + (time5 - time4));
System.out.println("linked查询效率:" + (time6 - time5));
//从尾部查询
long time7 = System.currentTimeMillis();
arr.add(4999990,"1");
long time8 = System.currentTimeMillis();
linked.add(4999990,"1");
long time9 = System.currentTimeMillis();
System.out.println("arr查询效率:" + (time8 - time7));
System.out.println("linked查询效率:" + (time9 - time8));
}
}
LinkedList©: 双向链表
1)底层实现:Node节点 -> date(数据) + next(下一个节点的引用)
底层数据结构: 链表
2)特点:
a.链表在内存中是固定顺序的,但是他的物理空间不连续
b.没有下标,只有头节点
c.所有的操作只能从头节点出发
d.头节点 head: 不存数据,只有next
4)优缺点:
优点: 插入/删除操作快
不需要连续的物理空间,所以空间使用率高
缺点: 查询速度,因为只能从头节点或尾节点开始查询
5)特有的方法:
只要带有first/last
addFirst(E e)
addLast(E e)
getFirst()
getLast()
removeFirst()
removeLast()
Vector©
底层实现:数组
和ArrayList一样
不一样的地方:
Vector加了锁(synchronized),线程安全,效率低
面试题:
ArrayList和LinkedList的区别
1.底层实现区别
2.优缺点的区别
对于插入/删除 单个操作而言 -> linkedList比较快
但是: 先查询,找到要插入/删除的位置的前一个节点
查询 + 插入(删除)
因为没有下标,所以查询非常慢
ArrayList和Vector的区别
1.线程安全分析
2.扩容容量
ArrayList扩容为原容量的1.5倍
Vector扩容为原容量的2倍
Queue(I) - 队列(线性结构)
1)特点:
a.先进先出
b.允许有重复值
2)常用方法:
offer() - 向队列尾部追加元素
peek() - 从队列头部获取元素,但是队列不变
poll() - 从队列头部获取元素,删除元素
3)子接口 - Dqueue(I) - 双端队列/栈
可以根据方法区分是双端队列还是栈
Dqueue中的栈实现:
push() - 压栈
pop() - 弹栈
package api05.Collection.queue;
import java.util.Deque;
import java.util.LinkedList;
/*
LinkedList作为双端队列实现
poll - 获取并删除数据
*/
public class LinkedDemo01 {
public static void main(String[] args) {
Deque linked = new LinkedList<>();
//linked.add("张三");
linked.offer("张三");
linked.offer("张三");
linked.offer("张三");
//Fitst/last
linked.offerLast("李四");
linked.offerFirst("lucy");
System.out.println(linked);
//获取并删除
Object poll = linked.poll();
System.out.println(poll);
System.out.println(linked);
}
}
package api05.Collection.queue;
import java.util.Deque;
import java.util.LinkedList;
/*
LinkedList作为栈实现
push - 添加
peek() - 获取但是不删除数据
pop() - 获取并删除数据
*/
public class LinkedDemo02 {
public static void main(String[] args) {
Deque linked = new LinkedList<>();
linked.push("张三");
linked.push("李四");
linked.push("王五");
System.out.println(linked);
//获取数据,但是不删除数据
Object pop = linked.peek();
System.out.println(pop);
System.out.println(linked);
//获取并删除数据 - 出栈(弹栈)
/*Object pop = linked.pop();
System.out.println(poll);
System.out.println(linked);*/
}
}
Set集合 - 散列表 (没有顺序的集合,不是随机!!!)
1.Set特点
a.无序且唯一
b.使用equals判断元素是否重复
c.Set的物理空间是不连续的
2.实现类
HashSet©:
特点:
a.存储位置不是真正的随机位置,根据HashCode方法计算(决定)最终位置
b.使用equals()判断元素是否重复
存储过程:
①.调用自身的hashCode()计算存储位置
②.判断该位置上是否存在元素
③.如果该位置上存在元素
则使用equals()判断是否相等
如果相等则不存入
如果不相等,则存放到链表末尾
package api05.Collection.set;
import java.util.HashSet;
public class HashSetDemo01 {
public static void main(String[] args) {
HashSet set = new HashSet();
User u1 = new User(18, "张三");
User u2 = new User(19, "张三");
set.add(u1);
set.add(u2);
u2.setAge(18);
System.out.println(set);
//通过HashSet中的构造方法 - 构建另一个集合
HashSet newSet = new HashSet(set);
System.out.println(newSet);
}
}
package api05.Collection.set;
import java.util.HashSet;
public class HashSetDemo02 {
public static void main(String[] args) {
HashSet<User> set = new HashSet<>();
User u1 = new User(18, "张三");
User u2 = new User(19, "李四");
User u3 = new User(18, "张三");
User u4 = new User(19, "李四");
set.add(u1);
set.add(u2);
set.add(u3);
set.add(u4);
System.out.println(set);
}
}
package api05.Collection.set;
import java.util.HashSet;
import java.util.Set;
public class HashSetDemo03 {
public static void main(String[] args) {
Set<User> set = new HashSet<User>();
User u1 = new User(18,"张三");
User u2 = new User(20,"李四");
set.add(u1);
set.add(u2);
System.out.println(set);
//修改了u2 的年龄
u2.setAge(23);
//删除u2的数据
set.remove(u2);
System.out.println(set);
//将数据修改成原数据 - 用另一个集合进行构建
}
}
package api05.Collection.set;
import java.util.HashSet;
import java.util.Set;
/*
Set集合的特点
*/
public class SetDemo01 {
public static void main(String[] args) {
//hashSet
//[how, are, hello, you]
//物理空间没有顺序 - 无序
Set set = new HashSet<>();
set.add("hello");
set.add("how");
set.add("are");
set.add("you");
System.out.println(set);
//[how, are, hello, you]
//特点二: 唯一
set.add("you");
set.add("you");
set.add("you");
System.out.println(set);
}
}
package api05.Collection.set;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.TreeSet;
/*
Comparator自定义排序
数组的排序方法:Arrays.sort() - 默认使用自然排序
List:Collections.sort() - 默认使用自然排序
Set: TreeSet() - 默认使用自然排序
Map: TreeMap() - 默认使用自然排序
自然排序: Comparable
重写 compareTo() -> 比较 o 和 this
自定义排序: Comparator
重写 compare() -> o1 和 o2
后 比 前 -> 倒序
前 比 后 -> 正序
*/
public class SortedDemo05 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
list.add(20);
list.add(12);
list.add(8);
list.add(55);
//对List集合进行排序 [8, 12, 20, 55]
//Collections.sort(list);//默认自然排序
//自定义排序 Comparator
Collections.sort(list, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
/*return o1 - o2;//正序*/
return o2 - o1;//倒序
}
});
System.out.println(list);
//__________________________________
//使用自定义排序对 TreeSet进行排序
TreeSet<User> set = new TreeSet(new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
return o1.getAge() - o2.getAge();
}
});
set.add(new User(18,"lucy"));
set.add(new User(19,"tom"));
set.add(new User(20,"tom"));
System.out.println(set);
}
}
package api05.Collection.set;
import java.util.TreeSet;
/*
TreeSet - 排序
*/
public class TreeSetDemo01 {
public static void main(String[] args) {
//[4, 7, 8, 11]
TreeSet<String> tree = new TreeSet();
//A - 65 a - 97
tree.add("a");
tree.add("A");
tree.add("b");
tree.add("B");
System.out.println(tree);
//ClassCastException - 类型转换异常
TreeSet<User> tree1 = new TreeSet<>();
User u1 = new User(18, "lucy");
User u2 = new User(19, "tom");
tree1.add(u1);
tree1.add(u2);
System.out.println(tree1);
}
}
package api05.Collection.set;
import java.util.Objects;
//实现Comparable接口 - 可排序
public class User /*implements Comparable<User>*/{
int age;
String name;
public User(int age, String name) {
this.age = age;
this.name = name;
}
public User() {
}
public int getAge() {
return age;
}
@Override
public boolean equals(Object object) {
if (this == object) return true;
if (object == null || getClass() != object.getClass()) return false;
User user = (User) object;
return age == user.age &&
Objects.equals(name, user.name);
}
@Override
public int hashCode() {
return Objects.hash(age, name);
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
/* 如果 return 0 ->
会认为存进来的所有数据都是一样的,不存入
如果 o 比 this 大 -> 正数
如果 o 比 this 小 -> 负数
this.age - o.age -> 正序
o.age - this.age -> 倒序
*/
/* @Override
public int compareTo(User o) {
// o 和 this(user)
*//*return this.age - o.age; 正序 *//*
if(o.age != this.age){
return o.age - this.age;
}
return o.name.compareTo(this.name);
}*/
}
二叉树
特点:
a.不允许有重复值
b.永远都是(左在前,右在后)
c.左节点 < 父节点 < 右节点
遍历方式:
先序遍历 - 中左右
后序遍历 - 左右中
中序遍历 - 左中右
TreeSet©
1)底层实现:二叉树
2)父接口 -> SortedSet(I)
3)特点:
a.用来排序,最常用的是中序遍历
4)TreeSet存储过程:
①.最开始的数据跟根节点比较 - compareTo进行比较
②.如果比根节点大,存储在右边
③.如果比根节点小,存储在左边
④.如果元素一样,则不存入
Comparable 自然排序 和 Comparator 自定义排序(指定比较器)
1)所有的自然排序,底层下都是实现了Comparable接口
2)自然排序 Comparable
重写了compareTo()
比较 obj 和 this 进行对比
数组: Arrays.sort()
List: Collections.sort()
Set: TreeSet()
Map: TreeMap()
3)比较器排序 Comparator
重写了compare()
比较 o1 和 o2
数组: Arrays.sort(new Comparator)
List: Collections.sort(new Comparator)
Set: TreeSet(new Comparator)
Map: TreeMap(new Comparator)
4)结论:
sort方法不指定比较器的时候,需要的元素必须是实现Comparable
sort方法指定比较器,元素不需要实现Comparable