上节回顾 List 是一个有序的,允许重复的Collection,其下的子类主要有 ArrayList LinkedList,Vector(这个官方不推荐使用)
那么同为list的子类,ArrayList 跟 LinkedList 有什么区别呢?
这里就涉及到了list的底层两种实现方式:
- 一种是数组 (ArayList)
数组的角标从0 开始 这个我们之前已经知道了,数组的好处查询快,有角标直接定位就好了,但是增删的效率比较慢
当进行删除一个元素操作时,其他元素需要向前或者向后移动
当进行增加一个元素操作时,需要考虑是否需要扩容(集合满了,要创建一个新的更大的数组,把旧数据复制进去)
所以增删比较慢
- 一种是链表 (LinkedList)
链表每个元素就不像数组了,它没有自己的角标
链表里面又有单向链表 跟 双向链表
先来看看单向链表
指针指向元素,每个元素分为两个域,一个是存储元素的 数据域,另一个是指向下一个元素的指针域
再来看看双向链表
双向链表就分为三个区域了,元素不用说,pre 是指向前一个元素,next: 是指向下一个元素
由于链表没有角标,所以查询起来需要一个一个从头往下查,然而增删相对于数组结构就快的多,删除他只需要继续指向下一个就行了,增加也是,前一个指针指向增加的元素
总结一下: ArrayList:数组结构,查询快,增删慢
LinkedList:链表结构,查询慢,增删快
那么怎么创建一个list集合呢?
很简单,万事万物皆对象,new一个,(按照具体需求来创建哪一个)
List<Integer> myList = new ArrayList<>();
List<Integer> myList = new linkedList<>();
可以看出这边就是多态的运用,向上转型
这边有些刚接触编程小伙伴会有疑惑了,这个 <> 是什么?
其实<> 代表泛型
官方是这样说的:泛型是 1.5中引入的一个新特性,其本质是参数化类型,也就是说所操作的数据类型被指定为一个参数(type parameter)这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
看不懂,没关系,说人话:
在这边集合中,泛型指的就是你这个集合装什么类型的数据,就好像我们整理东西,这个箱子放衣服,这个箱子放书本,可以理解成贴的标签,下次看一眼这个标签就知道这里面装的是什么
就像这个例子,这个集合里面装的是int (Integer,int 类型的包装类)类型的数据
既然集合容器我们创造出来了,不装点东西那不就是浪费了,所以我们来看看有哪些操作集合的方法
1. 遍历 (读取集合)
先来学习遍历,方便我们后续进行打印输出,除了跟数组遍历方法一样java 基础——数组 ,集合还多了一种遍历方式,自带的迭代器 (基本不用,不建议使用,拿来混个眼熟,知道有这么个东西)
List<Integer> myList = new ArrayList<>();
myList.add(1);
myList.add(3);
myList.add(5);
Iterator<Integer> it = myList.iterator();
while (it.hasNext()) {
Integer clone = it.next();
System.out.println(clone);
}
最主要我们还是使用 以下方式
ist<Integer> myList = new ArrayList<>();
myList.add(1);
myList.add(3);
myList.add(5);
for (int i = 0; i < myList.size(); i++) {
System.out.println(myList.get(i));
}
for (Integer item : myList) {
System.out.println(item);
}
myList.forEach(System.out::println);
jdk 1.8 新语法
输出结果:
1. 添加 (add)
添加是 直接添加数据
List<Integer> myList = new ArrayList<>();
myList.add(1);
myList.add(3);
myList.add(5);
- 移除 (remove)
移除是 按照角标来移除
List<Integer> myList = new ArrayList<>();
myList.add(1);
myList.add(3);
myList.add(5);
myList.remove(2);
for (Integer item : myList) {
System.out.println(item);
}
这里就是移除下标为2 的元素,下标为2 就是5 这个数据 ,结果:
3. 判断集合中是否有该元素(contains)
List<Integer> myList = new ArrayList<>();
myList.add(1);
myList.add(3);
myList.add(5);
boolean contains = myList.contains(3);
System.out.println(contains);
4. 获取集合的大小(size)
List<Integer> myList = new ArrayList<>();
myList.add(1);
myList.add(3);
myList.add(5);
int size = myList.size();
System.out.println(size);
5. 判断集合是否为空(isEmpty)
List<Integer> myList = new ArrayList<>();
myList.add(1);
myList.add(3);
myList.add(5);
boolean empty = myList.isEmpty();
System.out.println(empty);
6. 清空集合(clear)
List<Integer> myList = new LinkedList<>();
myList.add(1);
myList.add(3);
myList.add(5);
myList.clear();
LinkedList 相对于ArrayList 用的比较少,有些方法自己留个印象
LinkedList<Integer> myList = new LinkedList<>();
myList.add(1);
myList.add(3);
myList.add(9);
Integer first = myList.getFirst();
System.out.println(first);
输出结果:1
LinkedList<Integer> myList = new LinkedList<>();
myList.add(1);
myList.add(3);
myList.add(9);
Integer first = myList.getLast();
System.out.println(first);
输出结果:9
我们最后来简单看一下Vector, 这个东西在开发中不要用,Vector是线程安全的,这也是一个优点,但是它的效率低,其次Vector满了之后,扩容是一倍,ArrayList 仅仅是一半,面试中要是有问到,回答这些就好,java官方都不建议用这东西
最后我们来一个例子,来增强一下对List的理解
需求:有三个学生,学生对象存放在list中,他们呢都有自己的属性(学号,姓名,考试分数),然后把他们遍历打印出来
分析: 有个类,Student , 有三个私有属性(id,name,score)
public class Student {
private Integer id;
private String name;
private Double score;
public Student(Integer id, String name, Double score) {
this.id = id;
this.name = name;
this.score = score;
}
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", score=" + score +
'}';
}
}
public static void main(String[] args) {
List<Student> stuList = new ArrayList<>();
Student stu1 = new Student(1, "stu1", 100.0);
Student stu2 = new Student(2, "stu2", 95.5);
Student stu3 = new Student(3, "stu3", 90.0);
stuList.add(stu1);
stuList.add(stu2);
stuList.add(stu3);
for (Student student : stuList) {
System.out.println(student);
}
}
推荐阅读
java进阶—集合
|