集合概述
面向对象语言对事物的体现都是以对象的形式,为了方便对多个对象的操作,Java就提供了集合类。
数组和集合的区别:
- 长度区别:
数组的长度是固定的;集合的长度是可变的 - 存储数据类型的区别:
数组可以存储基本数据类型,也可以存储引用数据类型数据;集合只能存储引用数据类型 - 内容区别:
数组只能存储同种数据类型的元素;集合可以存储不同类型的元素
Collection集合
Collection集合是集合的顶层父接口,其继承体系如图:
下面先谈谈Collection集合吧。
Collection 层次结构 中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。
成员方法
将成员方法按功能分:
添加功能:
- boolean add(Object obj):添加一个元素
- boolean addAll(Collection c):添加一个集合的元素 (给一个集合添加进另一个集合中的所有元素)
删除功能:
- void clear():移除所有元素
- boolean remove(Object o):移除一个元素
- boolean removeAll(Collection c):移除一个集合的元素(移除一个以上返回的就是true) 删除的元素是两个集合的交集元素,如果没有交集元素 则删除失败 返回false
判断功能:
- boolean contains(Object o):判断集合中是否包含指定的元素
- boolean containsAll(Collection c):判断集合中是否包含指定的集合元素(这个集合 包含 另一个集合中所有的元素才算包含 才返回true)
- boolean isEmpty():判断集合是否为空
获取功能:
- Iterator iterator()(迭代器)
长度功能:
- int size():元素的个数
交集功能:
- boolean retainAll(Collection c):获取两个集合的交集元素(交集:两个集合都有的元素)
把集合转换为数组:
- Object[] toArray()
集合元素的遍历:
当集合的对象使用Collection类型来接收的时候,对于集合中的元素的遍历,有两种方式:
- 将集合转为数组,再进行遍历
public class Demo6 {
public static void main(String[] args) {
// 将3个学生的信息存储到数组中,并遍历数组,获取得到每一个学生信息
Student s1 = new Student("张三", 23);
Student s2 = new Student("李四", 21);
Student s3 = new Student("王五", 22);
Collection arrayList = new ArrayList();
arrayList.add(s1);
arrayList.add(s2);
arrayList.add(s3);
Object[] objects = arrayList.toArray();
for (int i = 0; i < objects.length; i++) {
Student stu= (Student) objects[i];
System.out.println(stu.getName()+"----"+stu.getAge());
}
}
}
class Student{
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
}
- 使用迭代器进行遍历
先获取迭代器,再判断是否有下一个元素(hasNext()方法),有的话就获取下一个元素(next()方法)。
public class Demo6 {
public static void main(String[] args) {
// 将3个学生的信息存储到数组中,并遍历数组,获取得到每一个学生信息
Student s1 = new Student("张三", 23);
Student s2 = new Student("李四", 21);
Student s3 = new Student("王五", 22);
Collection arrayList = new ArrayList();
arrayList.add(s1);
arrayList.add(s2);
arrayList.add(s3);
// 使用迭代器进行遍历
Iterator iterator = arrayList.iterator(); // 获取迭代器
while (iterator.hasNext()){
Object o = iterator.next();
Student stu = (Student) o;
System.out.println(stu.getName()+"----"+stu.getAge());
}
}
}
List集合
List中的元素特点:元素有序,并且每一个元素都存在一个索引。元素可以重复。
List集合的特有功能
由于List继承了Collection,所以Collection的方法List都可以使用,但它还有自己独特的功能。
常用的方法:
void add(int index,E element):在指定索引处添加元素
E remove(int index):移除指定索引处的元素 返回的是移除的元素
E get(int index):获取指定索引处的元素
E set(int index,E element):更改指定索引处的元素 返回的而是被替换的元素
集合元素的遍历:
当集合的对象使用List类型来接收的时候,对于集合中的元素的遍历,有以下几种方式:
- 由于List是Collection的子接口,所以Collection遍历元素的方式,List完全可以用。即可以将集合转换成数组,可以使用Collection的迭代器进行遍历。
- 由于List中有自己独特的迭代器(ListIterator),所以也可以使用List自己的迭代器来进行遍历。
public class Demo6 {
public static void main(String[] args) {
// 将3个学生的信息存储到数组中,并遍历数组,获取得到每一个学生信息
Student s1 = new Student("张三", 23);
Student s2 = new Student("李四", 21);
Student s3 = new Student("王五", 22);
//List arrayList = new ArrayList();
Collection arrayList = new ArrayList();
arrayList.add(s1);
arrayList.add(s2);
arrayList.add(s3);
// 使用列表迭代器进行遍历
ListIterator listIterator = arrayList.listIterator();
while (listIterator.hasNext()){
Object next = listIterator.next();
Student student= (Student) next;
System.out.println(student.getName()+"----"+student.getAge());
}
}
}
class Student{
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
}
需要注意的是,ListIterator 继承自Iterator 可以使用Iterator中的方法,同时,ListIterator有自己的特有功能:
boolean hasPrevious(): 是否存在前一个元素
E previous(): 返回列表中的前一个元素
以上两个方法可以实现反向遍历 但是注意 要完成反向遍历之前 要先进行正向遍历 这样指针才能移到最后。如果直接反向遍历是没有效果的 因为指针默认位置就在最前面,他前面没有元素。
- List中有一个get()方法,用于获取对应索引处的元素值。所以可以结合size()方法和get()方法来进行遍历。
public class Demo6 {
public static void main(String[] args) {
// 将3个学生的信息存储到数组中,并遍历数组,获取得到每一个学生信息
Student s1 = new Student("张三", 23);
Student s2 = new Student("李四", 21);
Student s3 = new Student("王五", 22);
//List arrayList = new ArrayList();
Collection arrayList = new ArrayList();
arrayList.add(s1);
arrayList.add(s2);
arrayList.add(s3);
// 使用size和get方法进行遍历
for (int i = 0; i < arrayList.size(); i++) {
Object o = arrayList.get(i);
Student student= (Student) o;
System.out.println(student.getName()+"----"+student.getAge());
}
}
}
class Student{
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
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;
}
}
List下有多个子类,但常用的子类有ArrayList、Vector、LinkedList。
这三个子类的特点为:
- ArrayList
底层数据结构是数组,查询快,增删慢
线程不安全,效率高 - Vector
底层数据结构是数组,查询快,增删慢
线程安全,效率低 - LinkedList
底层数据结构是链表,查询慢,增删快
线程不安全,效率高
那么问题来了,在这三个类中我们该如何选择使用呢?
看我们程序的需求,是要安全还是要效率以及是要查找多还是增删多,依据这些来选择我们需要使用的子类。
下面来谈谈这三个子类。
ArrayList
List 接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括 null 在内的所有元素。除了实现 List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。
每个 ArrayList 实例都有一个容量。该容量是指用来存储列表元素的数组的大小。它总是至少等于列表的大小。随着向 ArrayList 中不断添加元素,其容量也自动增长。并未指定增长策略的细节,因为这不只是添加元素会带来分摊固定时间开销那样简单。
构造方法:
成员方法:
集合元素的遍历:
由于ArrayList是List的子类,所以可以使用转换成数组、迭代器以及size()和get方法结合的方式进行元素的遍历,除此之外还可以用JDK1.8新增的一个方法void forEach(Consumer<? super E> action) 遍历元素。
void forEach(Consumer<? super E> action) 执行特定动作的每一个元素的 Iterable直到所有元素都被处理或操作抛出异常 。
Vector
Vector 类可以实现可增长的对象数组, Vector 是同步的。与数组一样,它包含可以使用整数索引进行访问的组件。但是,Vector 的大小可以根据需要增大或缩小,以适应创建 Vector 后进行添加或移除项的操作。
构造方法
成员方法
LinkedList
List 接口的链接列表实现,此实现不是同步的。实现所有可选的列表操作,并且允许所有元素(包括 null)。除了实现 List 接口外,LinkedList 类还为在列表的开头及结尾 get、remove 和 insert 元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列或双端队列。
构造方法
成员方法