文章目录
集合
java中的集合像一个容器,是用来存放对象的容器,按照其存储结构分为两大类:单例集合Collection和双列集合Map,其特点如下:
- Collection:单例集合的根接口,存放一系列的符合某种规则的元素,其有两个子接口,List和Set;其中,List接口的特点为:元素有序,可重复;Set集合的特点为:元素无序,不可重复
- Map:双列集合的根接口,存储具有键(key),值(value)映射关系的元素。
HashMap:底层为哈希桶,查询时间复杂度为O(1)
TreeSet:底层为红黑树,查询的时间复杂度为O( ㏒₂N),关于key有序的
- Stack: 栈,实现了一个后进先出的数据结构。
- Queue:队列。
- Deque:接口
- SortedMap:使 Key 保持在升序排列。
- Set:集合,是一个接口,里面放置的是K模型
HashSet:底层为哈希桶,查询的时间复杂度为O(1);
TreeSet:底层为红黑树,查询的时间复杂度为O(㏒₂N ),关于key有序的
List接口
我们按照顺序来介绍下面的接口和类
Iterable接口
实现该接口的类是可以逐个元素遍历的,具体方法如下:
Collection接口
该接口为其规定了单列集合的通用 方法:
List接口
List接口提供专属于List特有的方法
我们介绍一下List的常用方法
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
/**
* boolean add(E e) 尾插e
*/
list.add(5);
list.add(4);
list.add(4);
list.add(3);
list.add(2);
list.add(1);
/**
* void add(int index, E element) 把元素e插入index位置
*/
list.add(0,1);
/**
* boolean addAll(Collection<? extends E> c) 尾插c中属于元素
*/
List<Integer> list1 = new ArrayList<>();
list1.add(6);
list.addAll(list1);
/**
* boolean removeAll(int index) 删除index位置的元素
*/
list.remove(1);
/**
* boolean remove(Object o) 删除遇到的第一个o
*/
list.remove(new Integer(3));
/**
* E get(int index) 获取下标 index 位置元素
*/
int elem = list.get(2);
System.out.println(elem);
/**
* E set(int index, E element) 将下标 index 位置元素设置为 element
*/
list.set(2,13);
System.out.println(list.get(2));
/**
* boolean contains(Object o) 判断 o 是否在线性表中
*/
System.out.println(list.contains(new Integer(13)));
/**
*int indexOf(Object o) 返回第一个 o 所在下标
*/
System.out.println(list.indexOf(new Integer(13)));
//list.indexOf(13) 这样也可以,会自动装箱
/**
* int lastIndexOf(Object o) 返回最后一个 o 的下标
*/
System.out.println(list.lastIndexOf(1));
/**
* List<E> subList(int fromIndex, int toIndex) 截取部分 list
*/
list1 = list.subList(0,4);//左闭右开[0,4)
list1.set(0,13);
//修改截取部分的元素,原本的元素也会发生改变
System.out.println(list.get(0));
/**
* void clear() 清空
*/
System.out.println(list.toString());
list.clear();
System.out.println(list.toString());
}
ArrayList与顺序表
线性表
线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串…
线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储.
顺序表
顺序表在物理地址上是连续的,在其存储单元是依次存储数据元素的线性结构,一般是用数组来存储
ArrayList介绍
解释:
接口说明:
- RandomAccess接口:标识实现该接口的类支持快速随机访问。
- Cloneable接口 : 作用是使一个类的实例能够将自身拷贝到另一个新的实例中.
- Serializable接口: 实现java.io.Serializable 接口的类是可序列化的
ArrayList类拥有上面接口的特性
- 和Vector不同,ArrayList不是线程安全的,在单线程下可以使用,在多线程中可以选择Vector或者
CopyOnWriteArrayList- ArrayList底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表
ArrayList使用
ArrayList构造器
方法 | 说明 |
---|---|
public ArrayList(int initialCapacity) | 根据参数值创建该大小的ArrayList |
public ArrayList() | 无参构造 |
ArrayList(Collection<? extends E> c) | 接受Collection接口的容器构建ArrayList |
一般情况下。我们都是用无参构造方法;但提供观察源代码,我们发现最开始是一个空数组
现在我们add一些元素
结论:利用无参构造时,默认为空数组;只有在第一次add时,大小才变为10;扩容为1.5倍扩容
ArrayList操作方法
package Package1;
import java.util.ArrayList;
import java.util.List;
public class Test1 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
/**
* boolean add(E e) 尾插e
*/
list.add(1);
list.add(12);
list.add(123);
list.add(1234);
list.add(12345);
/**
* public int size() 获取容器有效元素个数
*/
System.out.println(list.size());
/**
* void add(int index, E element) 把元素e插入index位置
*/
list.add(0,12345);
/**
* boolean addAll(Collection<? extends E> c) 尾插c中属于元素
*/
List<Integer> list1 = new ArrayList<>();
list1.add(123456);
list.addAll(list1);
/**
* boolean removeAll(int index) 删除index位置的元素
*/
list.remove(1);
/**
* boolean remove(Object o) 删除遇到的第一个o
*/
list.remove(new Integer(123456));
/**
* E get(int index) 获取下标 index 位置元素
*/
int elem = list.get(1);
System.out.println(elem);
/**
* E set(int index, E element) 将下标 index 位置元素设置为 element
*/
list.set(2,13);
System.out.println(list.get(2));
/**
* boolean contains(Object o) 判断 o 是否在线性表中
*/
System.out.println(list.contains(1234));
/**
*int indexOf(Object o) 返回第一个 o 所在下标
*/
System.out.println(list.indexOf(12345));
/**
* int lastIndexOf(Object o) 返回最后一个 o 的下标
*/
System.out.println(list.lastIndexOf(12345));
/**
* List<E> subList(int fromIndex, int toIndex) 截取部分 list
*/
list1 = list.subList(0,2);//左闭右开[0,2)
list1.set(0,13);
//修改截取部分的元素,原本的元素也会发生改变
System.out.println(list.get(0));
/**
* void clear() 清空
*/
System.out.println(list.toString());
list.clear();
System.out.println(list.toString());
}
}
ArrayList的遍历
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
list.add(i);
}
/**
* for循环
*/
//普通for循环
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i) + " ");
}
//For-each循环
for (Integer x : list) {
System.out.print(x + " ");
}
/**
* 链表转数组
*/
Integer[] intArray = new Integer[list.size()];
list.toArray(intArray);
for (int x :intArray) {
System.out.print(x + " ");
}
for (int i = 0; i < intArray.length; i++) {
System.out.print(intArray[i] + " ");
}
/**
* 迭代器
*/
Iterator<Integer> it = list.iterator();
while (it.hasNext()) {
System.out.print(it.next() + " ");
}
迭代器
ListIterator 是 Collection中的接口, 它扩展了 Iterator 接口,新增了多个方法;
方法 | 解释 |
---|---|
E next() | 返回迭代器的下一个元素,并且更新迭代器的状态。 |
boolean hasNext() | 检测集合中是否还有元素 |
void remove() | 将迭代器返回的元素删除 |
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("Hello");
list.add("Wow");
list.add("Hi");
ListIterator<String> it = list.listIterator();
it.add("qqq");
while (it.hasNext()) {
//返回迭代器当前指向的元素的下标
System.out.print(it.nextIndex()+" ");
//得到迭代器中的下一个元素,并且更新迭代器状态
System.out.print(it.next() + " ");
}
}
ArrayListde的模拟实现
package Package1;
import java.lang.*;
import java.util.Arrays;
public class SeqList {
private int[] MyArrayList = new int[5];
private int usedSize;
// 打印顺序表
public void display() {
for (int i = 0; i < usedSize ; i++) {
System.out.print(MyArrayList[i] + " ");
}
System.out.println();
}
// 新增元素,默认在数组最后新增
public void add(int data) {
//判断是否满
if (isFull()) {
grow();
}
this.MyArrayList[usedSize++] = data;
}
//检查数组是否满
public boolean isFull() {
// if(usedSize == ArrayList.length) {
// return true;
// }
// return false;
//代码可以优化
return this.usedSize == MyArrayList.length;
}
//扩容
public void grow() {
MyArrayList = Arrays.copyOf(MyArrayList,MyArrayList.length*2);
}
//判断pos是否合法
private void check(int pos) {
if (pos < 0 || pos > this.usedSize) {
throw new MyArrayIndexOutOfBoundsException("pos下标越界");
}
}
// 在 pos 位置新增元素
public void add(int pos, int data) {
check(pos);
//是否需要扩容
if (isFull()) {
grow();
}
//插入元素
//方法1:
for (int i = usedSize - 1; i >= pos ; i--) {
this.MyArrayList[i + 1] = this.MyArrayList[i];
}
//方法2:
//System.arraycopy(MyArrayList,pos,MyArrayList,pos+ 1,usedSize - pos);
this.MyArrayList[pos] = data;
usedSize++;
}
// 判定是否包含某个元素
public boolean contains(int toFind) {
for (int i = 0; i < usedSize; i++) {
if (MyArrayList[i] == toFind) {
return true;
}
}
return false;
}
// 查找第一次元素对应的位置
public int indexOf(int toFind) {
for (int i = 0; i < usedSize; i++) {
if (MyArrayList[i] == toFind) {
return i;
}
}
return -1;
}
// 查找最后出现元素对应的位置
public int lastIndexOf(int toFind) {
int index = -1;
for (int i = usedSize - 1; i >= 0; i--) {
if (this.MyArrayList[i] == toFind) {
index = i;
}
}
return index;
}
// 获取 pos 位置的元素
public int get(int pos) {
check(pos);
return this.MyArrayList[pos];
}
// 给 pos 位置的元素设为 value
public void set(int pos, int value) {
//判断pos是否合法
check(pos);
this.MyArrayList[pos] = value;
}
//判断顺序表是否为空
public boolean isEmpty() {
return this.MyArrayList.length == 0;
}
//删除第一次出现的关键字key
public void remove(int toRemove) {
//顺序表是否为空
if (isEmpty()) {
throw new MyArrayIsEmptyException("链表为空!");
}
//查找是否含有该元素
if (!contains(toRemove)) {
throw new MyArrayListNoSuchElementException("不存在该元素");
}
int index = indexOf(toRemove);
for (int i = index; i < usedSize; i++) {
this.MyArrayList[i] = this.MyArrayList[i + 1];
}
usedSize--;
}
// 获取顺序表长度
public int size() {
return this.usedSize;
}
// 清空顺序表
public void clear() {
for (int i = 0; i < usedSize; i++) {
MyArrayList[i] = 0;
}
usedSize = 0;
}
}
public class MyArrayIndexOutOfBoundsException extends RuntimeException{
public MyArrayIndexOutOfBoundsException() {
super();
}
public MyArrayIndexOutOfBoundsException(String message) {
super(message);
}
}
public class MyArrayIsEmptyException extends RuntimeException{
public MyArrayIsEmptyException() {
super();
}
public MyArrayIsEmptyException(String message) {
super(message);
}
}
public class MyArrayListNoSuchElementException extends RuntimeException{
public MyArrayListNoSuchElementException() {
super();
}
public MyArrayListNoSuchElementException(String message) {
super(message);
}
}
常用工具类
Collections工具类
Collections类提供大量的静态方法来对集合元素进行排序,查找,修改等操作,下面我们学习一些常用方法:
排序,添加操作
方法 | 解释 |
---|---|
public static void shuffle(List<?> list) | 对list中元素随机排序 |
public static boolean addAll(Collection<? super T> c, T… elements) | 把 T… elements中元素全部添加到list中 |
public static void reverse(List<?> list) | 对list所有元素逆序 |
public static void swap(List<?> list, int i, int j) | 交换list中指定元素 |
public static <T extends Comparable<? super T>> void sort(List list) | 对list按照自然属性排序 |
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 6; i++) {
list.add(i);
}
Collections.shuffle(list);
System.out.println(list);
Collections.addAll(list,11,22,33);
System.out.println(list);
Collections.reverse(list);
Collections.swap(list,0,2);
Collections.sort(list);
System.out.println(list);
}
查找,替换操作
方法 | 解释 |
---|---|
int binarySearch(List T key) | 二分查找法,首先保证集合有序 |
public static T max(Collection coll) | 返回最大值 |
public static T min(Collection coll) | 返回最小值 |
public static boolean replaceAll(List list, T oldVal, T newVal) | 把所有oldVal替换为newVal |
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
Collections.addAll(list,1,2,3,4,5,6,1,2,3,8,6);
Collections.sort(list);
System.out.println(Collections.binarySearch(list, 1));
System.out.println(Collections.max(list));
System.out.println(Collections.min(list));
Collections.replaceAll(list,4,1);
System.out.println(list);
Arrays工具类
听名字可以知道这个是针对数组的工具类,它提供大量处理数组的静态方法,如排序,操作,拷贝,替换等操作
方法 | 解释 |
---|---|
public static void sort(int[] a) | 按照自然顺序排序 |
public static String toString(int[] a) | 数组转为字符串 |
public static int[] copyOf(int[] original, int newLength) | 返回newLength长度的数组,通常用于扩容 |
public static int binarySearch(int[] a, int key) | 有序的前提下,二分查找 |
public static int[] copyOfRange(int[] original, int from, int to) | 把[form.to)的元素拷贝到新数组并返回 |
public static void fill(int[] a, int val) | 把数组中所有元素替换为val |
public static void main(String[] args) {
int[] arr = {1,2,3,9,8,7,6,3,4};
Arrays.sort(arr);
System.out.println(Arrays.toString(arr));
arr = Arrays.copyOf(arr,arr.length*2);
System.out.println(Arrays.binarySearch(arr, 4));
int[] copyArray = Arrays.copyOfRange(arr,0,arr.length);
System.out.println(Arrays.toString(copyArray));
Arrays.fill(arr,1);
System.out.println(Arrays.toString(arr));
}