本篇目标
概述
- 集合又称对象的容器,定义了对多个对象进行操作的常用方法。可实现数组的功能。
- 与数组的区别:
- (1)数组长度固定,集合长度可变
- (2)数组可以存储基本类型和引用类型,集合只能存储引用类型
- 位置:
java.util.*
各集合继承关系如图:
JDK快速访问地址
一、Collection 接口
二、Iterator 接口
boolean hasNext()
如果仍有元素可以迭代,则返回true
E next()
返回迭代的下一个元素NoSuchElementException
— 没有元素可以迭代。
void remove()
从迭代器指向的collection
中移除迭代器返回的最后一个元素,每次调用next
只能调用一次此方法。UnsupportedOperationException
— 迭代器不支持remove
操作IllegalStateException
— 如果尚未调用next
方法,或者在上一次调用next
方法之后已经调用了remove
方法
@example:
import java.util.*;
/**
* @author Nigori
* @date 2020/7/31
**/
public class CollectionDemo {
public static void main(String[] args) {
//实例化集合对象
Collection<String> collection = new ArrayList<>();
//添加数据
collection.add("aaa");
collection.add("sss");
collection.add("ddd");
System.out.println("集合中元素个数:"+collection.size()); //获取集合中元素的个数
System.out.println(collection.isEmpty()); //判断集合是否为空
System.out.println(collection.contains("sss")); //判断集合中是否有某个元素
//集合转换成数组
Object[] objects = collection.toArray();
for (int i = 0; i < objects.length; i++) {
System.out.println(objects[i]);
}
System.out.println("=====================");
//创建迭代器
/**
* 注意:迭代器的泛型与集合泛型保持一致
*/
Iterator<String> iterator = collection.iterator();
while (iterator.hasNext()) { //判断是否有下一个元素
//获取集合中元素
String str = iterator.next();
//collection.remove(str); //抛ConcurrentModificationException异常
System.out.println(str);
}
System.out.println("=====================");
//增强for循环遍历集合
/**
* for(容器数据类型 变量名:容器名) { sout(变量名);}
*/
for (String str:collection) {
System.out.println(str);
}
}
}
三、List 接口
特点:List集合有索引、可存储重复元素、可以保证存取顺序
注意:
IndexOutOfBoundsException:集合索引越界异常
ArrayIndexOutOfBoundsException:数组索引越界异常
StringIndexOutOfBoundsException:字符串索引越界异常
常用方法:(index :索引【从零开始】)
void add(int index, E element);
将指定元素插入该集合指定位置 ★★★E get(int index);
返回获取指定位置的元素 ★★★E remove(int index)
返回移除列表中指定位置的元素 ★★★E set(int index, E element);
用指定元素替换集合中指定位置的元素,返回替换前的元素 ★★★boolean addAll(int index, Collection<? extends E> c);
将指定 collection 中的所有元素都插入到列表中的指定位置int indexOf(Object o)
返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回 -1int lastIndexOf(Object o)
返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回 -1ListIterator<E> listIterator()
返回此列表元素的列表迭代器(按适当顺序)ListIterator<E> listIterator(int index)
返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始List<E> subList(int fromIndex, int toIndex)
返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图
import java.util.ArrayList;
import java.util.List;
/**
* @author Nigori
* @date 2020/5/13
**/
public class ListTest {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("ccc");
list.add("vvv");
list.add("mmm");
list.add(2,"aaa");
System.out.println("get()方法:"+list.get(1)); //get()方法:vvv
System.out.println("set()方法:"+list.set(2, "lll")); //set()方法:aaa
System.out.println("remove()方法:"+list.remove(3)); //remove()方法:mmm
/**
* 假如为 Integer类型:list.remove(new Integer(30));
* list.remove((Object)20);
*/
list.remove("ccc");
System.out.println(list.toString()); // [vvv, lll]
//遍历集合
ListIterator<String> listIterator = list.listIterator();
//顺序遍历
while (listIterator.hasNext()) {
System.out.println(listIterator.nextIndex() + ":" + listIterator.next());
}
System.out.println();
//逆序遍历
while (listIterator.hasPrevious()) {
System.out.println(listIterator.previousIndex() + ":" + listIterator.previous());
}
//subList 方法,左闭右开
List<String> subList = list.subList(1, 2);
System.out.println(subList.toString()); // [lll]
}
}
(一)ListIterator 接口( extends Iterator 接口)
(二)List 的常用实现类:ArrayList 与 LinkedList
1、ArrayList 实现可变数组保存数据
特点:底层实现是数组,故查询快,增删慢。
Arraylist 中存储引用类型,若要存储基本类型,必须使用基本类型对应的 “包装类”
基本类型 | 包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
Double | Double |
char | Character |
boolean | Boolean |
ArrayList 源码分析 (重点)
DEFAULT_CAPACITY = 10;
默认容量大小Object[] elementData;
存放元素的数组Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = { }
size;
实际元素的个数- 如果没有向集合中添加任何元素时,容量为 0;添加一个元素之后,容量为 10;每次扩容大小是原来的 1.5 倍(即添加第11个元素时,容量为15)。
public ArrayList() { //无参构造
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
@example1:
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* @author Nigori
* @date 2020/5/12
*
* 生成6个1~33之间的随机整数,添加到集合,并遍历集合
*
**/
public class ArrayListTest_01 {
public static void main(String[] args) {
//创建集合
List<Integer> list = new ArrayList<>();
//产生随机整数
Random random = new Random();
for (int i=0;i<6;i++) {
int num = random.nextInt(33)+1;
//添加数据到集合
list.add(num);
}
//遍历并获取数据
for (int i=0;i<list.size();i++) {
System.out.println(list.get(i));
}
}
}
@example2:
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* @author Nigori
* @date 2020/5/12
*
* 大集合存放20个随机数字,筛选偶数元素放入到小集合中,使用自定义实现筛选
*
**/
public class ArrayListTest_02 {
public static void main(String[] args) {
//创建大集合
List<Integer> bigList = new ArrayList<>();
//存放随机数据
Random random = new Random();
for (int i=0;i<20;i++) {
int num = random.nextInt(100)+1;
bigList.add(num);
}
//获取小集合的元素
ArrayList<Integer> smallList = selectSmallList(bigList);
for (int i=0;i<smallList.size();i++) {
System.out.println(smallList.get(i));
}
}
//筛选符合条件的元素
public static ArrayList<Integer> selectSmallList(List<Integer> bigList) {
//创建小集合
ArrayList<Integer> smallList = new ArrayList<>();
//存放满足条件的数据
for (int i=0;i<bigList.size();i++) {
if (bigList.get(i)%2 == 0) {
smallList.add(bigList.get(i));
}
}
return smallList;
}
}
2、LinkedList 采用链表结构保存对象
特点:底层实现是双向链表,故查询慢,增删快。使用 LinkedList 集合特有的方法时,不能使用多态。
LinkedList 源码分析 (重点)
LinkedList 的主要属性:
//链表节点的个数
transient int size = 0;
//链表首节点
transient Node<E> first;
//链表尾节点
transient Node<E> last;
LinkedList 的特有方法:
public void addFirst(E,e);
指定元素插入此链表的开头
public void push(E,e);
public void addLast(E,e);
指定元素插入此链表的末尾
public void add(E,e);
public E getFirst();
返回此链表的第一个元素
public E getLast();
返回此链表的最后一个元素
public E removeFirst();
移除并返回此链表的第一个元素
public E pop();
public E removeLast();
移除并返回此链表的最后一个元素
public boolean isEmpty();
判断链表是否为空
@example:
import java.util.LinkedList;
/**
* @author Nigori
* @date 2020/5/13
**/
public class LinkedListTest {
public static void main(String[] args) {
addElement();
}
public static void addElement() {
LinkedList<String> linkedList= new LinkedList<>();
linkedList.add("aaa");
linkedList.add("sss");
linkedList.add("ddd");
//增加到链表首位置
linkedList.addFirst("fff");
//增加到链表的末位置
linkedList.addLast("lll");
System.out.println("链表是否为空:"+linkedList.isEmpty());
System.out.println(linkedList+"\n\n=====================\n");
//增加到链表首位置
linkedList.push("fffFirst");
//增加到链表的末位置
linkedList.add("lllList");
System.out.println(linkedList+"\n\n=====================\n");
System.out.println("链表第一个元素:"+linkedList.getFirst());
System.out.println("链表最后一个元素:"+linkedList.getLast());
System.out.println("移除链表的第一个元素:"+linkedList.removeFirst());
System.out.println("移除链表的最后一个元素:"+linkedList.removeLast());
System.out.println(linkedList+"\n\n=====================\n");
System.out.println("移除链表的第一个元素:"+linkedList.pop());
System.out.println("移除链表的第一个元素:"+linkedList.remove());
System.out.println(linkedList+"\n\n=====================\n");
}
}
3、Vector(了解)
特点(JDK 1.0):底层实现是数组,故查询快,增删慢。运行效率慢,线程安全。
Vector vector = new Vector();
vector.add("西瓜");
vector.add("芒果");
vector.add("葡萄");
System.out.println(vector.toString());
//使用Vector特有的 Enumeration 遍历
Enumeration enumeration = vector.elements();
while (enumeration.hasMoreElements()) {
System.out.println((String) enumeration.nextElement());
}