概述
Java集合是使程序能够存储和操纵元素不固定的一组数据。 所有Java集合类都位于java.util包中。
通过对比数组和Java集合工具类来解释Java集合工具类的必要性
1.1 继承体系
Collection 是集合,两个直接子接口是List和set
List 特性 : 有序 可重复,保证数据的添加顺序和取出顺序一致
Set 特性 : 无序 不可重复,不能保证数据的添加和取出顺序一致
List 有三个子类 :
ArrayList : 底层是数组,查询和更改效率极高
LinkedList : 底层是双向链表,添加和删除效率要高一些
Vector : 底层也是数组,是线程安全,已废弃,不推荐使用,已被ArrayList代替
Set有两个子类
HashSet : 底层是散列表
TreeSet : 底层是二叉树
1. Collection
Collection作为集合类的父类,所以,collection中的方法,是所有集合类都有的方法
常用方法
public static void main(String[] args) {
LinkedList list = new LinkedList();
// ArrayList list = new ArrayList();
// 添加 到尾部
list.add(1);
list.add(11);
list.add(12);
list.add(13);
// 添加到指定位置
// list.add(index, element);
// 添加到头部
// list.push(e);
// list.addFirst(e);
// 尾部添加
// list.addLast(e);
// 个数
System.out.println(list.size());
// 是否为空
System.out.println(list.isEmpty());
// 根据下标删除
list.remove(0);
// 根据数据删除
list.remove(new Integer(11));
// 清空
list.clear();
// 更改
list.set(2, 111);
// 获取
list.get(2);
// 遍历
for (Object object : list) {
}
}
1.1.1 使用方式
public static void main(String[] args) {
// 100W条数据为例
// 尾部添加
long startTime = System.currentTimeMillis();
// addToArrayList();
pushToArrayList();
long endTime = System.currentTimeMillis();
System.out.println("ArrayList添加完成,耗时 : " + (endTime - startTime));
startTime = System.currentTimeMillis();
// addToLinkedList();
pushToLinkedList();
endTime = System.currentTimeMillis();
System.out.println("LinkedList添加完成,耗时 : " + (endTime - startTime));
// 尾部添加 100W ArrayList 29 LinkedList 169
// 首部添加 10W ArrayList 599 LinkedList 10
}
public static void pushToArrayList() {
ArrayList list = new ArrayList();
for (int i = 1; i <= 100000; i++) {
list.add(0, i);
}
}
public static void pushToLinkedList() {
LinkedList list = new LinkedList();
for (int i = 1; i <= 100000; i++) {
list.addFirst(i);
}
}
public static void addToArrayList() {
ArrayList list = new ArrayList();
for (int i = 1; i <= 1000000; i++) {
list.add(i);
}
}
public static void addToLinkedList() {
LinkedList list = new LinkedList();
for (int i = 1; i <= 1000000; i++) {
list.add(i);
}
}
以ArrayList为例
Iterator
迭代器
注意
forEach
List
ArrayList
LinkedList
基本使用
底层实现
节点类
链表由节点构成,因为是双向链表,所以节点中有三个属性
1 保存的数据 Object
2 下一个节点对象 节点类型
3 上一个节点对象 节点类型
LinkedList类
为了首尾添加效率更高,在LinkedList类中保存了首节点和尾结点
添加-add
取-get
获取数据
Get方法只是模拟下标获取的方式而已,本质上就是遍历操作
只不过做了一定的判断,判断找前半截快还是找后半截快
Set和排序
TreeSet
Comparable
因为 User没有实现对应的Comparable接口,所以在使用TreeSet的时候,会报错
Comparator
public static void main(String[] args) {
// 把比较器类的对象传入
// TreeSet set = new TreeSet(new A());
// 匿名内部类写法
TreeSet set = new TreeSet(new Comparator () {
@Override
public int compare(Object o1, Object o2) {
// o1 是要添加的元素
// o2 是集合中的元素
Integer i1 = (Integer) o1;
Integer i2 = (Integer) o2;
// 该方法 返回 0 说明重复,不添加
// 返回 大于0的值 说明要添加的元素比集合中的大,就往后放
// 返回 小于0的值 说明要添加的元素比集合中的元素小,就往前放
return i2-i1;
}
});
set.add(1);
set.add(2);
set.add(3);
set.add(4);
System.out.println(set);
}
}
// 比较器类
class A implements Comparator{
@Override
public int compare(Object o1, Object o2) {
// o1 是要添加的元素
// o2 是集合中的元素
Integer i1 = (Integer) o1;
Integer i2 = (Integer) o2;
// 该方法 返回 0 说明重复,不添加
// 返回 大于0的值 说明要添加的元素比集合中的大,就往后放
// 返回 小于0的值 说明要添加的元素比集合中的元素小,就往前放
return i2-i1;
}
List排序
public static void main(String[] args) {
List list = new ArrayList();
list.add(1);
list.add(22);
list.add(3);
list.add(11);
// 该方法会调用对象的Comparable中的compareTo方法或者是Comparator接口中的方法
// 因为Integer中有compareTo方法,而且是升序,所以才可以使用sort方法
// 比如想要降序可以使用sort方法重载
// Collections.sort(list);
Collections.sort(list, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
// o1 是要添加的元素
// o2 是集合中的元素
Integer i1 = (Integer) o1;
Integer i2 = (Integer) o2;
// 该方法 返回 0 说明重复,不添加
// 返回 大于0的值 说明要添加的元素比集合中的大,就往后放
// 返回 小于0的值 说明要添加的元素比集合中的元素小,就往前放
return i2 - i1;
}
});
System.out.println(list);
list = new ArrayList();
list.add(new Student1(18));
list.add(new Student1(11));
list.add(new Student1(15));
list.add(new Student1(4));
// 因为Student1没有实现comparable接口 所以不能使用sort方法
// Collections.sort(list);
// 但是可以使用重载的方法
Collections.sort(list,new Comparator () {
@Override
public int compare(Object o1, Object o2) {
return 0;
}
});
}
}
class Student1 {
int age;
public Student1(int age) {
super();
this.age = age;
}
总结
* Comparable : 如果treeSet中保存我们自己定义的类型的时候,使用Comparable
* Comparator : 如果treeSet中保存的不是我们写的类型的时候,就要使用Comparator来指定排序规则
* 比如 Integer 默认是升序排序,假如我们需要降序排序,我们只能使用 Comparator,因为我们不可能去更改Integer的源码
* 但此时 Integer中是有Comparable接口的实现的,等于两个比较都存在,但是Comparator优先级高,
* 所以会按照我们定义的规则进行排序
* 开闭原则 : 对修改关闭,对扩展开发
*