容器框架图:
Collection接口
Set接口:Collection的子接口>>无序不可重复
HashSet:Set接口的实现类
List接口:Collection的子接口>>有序可重复
ArrayList:Lis接口t的实现类(数组列表)查询效率高
LinkedList:List接口的实现类(链表)增删效率高
Vector:List接口的实现类(底层是数组)线程安全
Map接口
HashMap:Map接口的实现类
Collection< E >接口常用方法
下面的方法一般用于2个容器间的操作;不过也可以使用1个容器,自己与自己进行交、并、差等操作,一般没这个必要。
注意:2个容器的数据类型必须一致
代码测验如下:
import java.util.ArrayList;
import java.util.Collection;
public class TestCollection {
public static void main(String[] args) {
Collection<String> coll = new ArrayList<>();
coll.add("1");
coll.add("2");
coll.add("3");
System.out.println(coll);//[1, 2, 3]
coll.clear();
System.out.println(coll);//[]
coll.add("A");
coll.add("B");
coll.add("C");
coll.add("DE");
System.out.println(coll);//[A, B, C, DE]
// coll.remove(2);//这里表示的含义是移除整数2,而不是移除数组下标为2的元素
coll.remove("DE");
System.out.println(coll);//[A, B, C]
int a = coll.size();
System.out.println(a);//3
boolean b = coll.isEmpty();
System.out.println(b);//false
boolean c = coll.contains("A");
System.out.println(c);//true
Object[] d = coll.toArray();
System.out.println(d);//[Ljava.lang.Object;@15db9742
System.out.println("=========================================");
Collection<String> coll02 = new ArrayList<>();
coll02.add("B");
coll02.add("C");
coll02.add("D");
System.out.println("coll:"+coll);//coll:[A, B, C]
System.out.println("coll02:"+coll02);//coll02:[B, C, D]
boolean e = coll.containsAll(coll02);
System.out.println(e);//false
coll.retainAll(coll02);
System.out.println(coll);//[B, C]
coll.addAll(coll02);
System.out.println(coll);//[B, C, B, C, D]
coll.removeAll(coll02);
System.out.println(coll);//[]
}
}
List< E >接口常用方法
代码测验如下:
import java.util.ArrayList;
import java.util.List;
/**
* List接口中的方法多加了一个索引、下标
*/
public class TestList {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
System.out.println(list);//[1, 2, 3, 4, 5]
list.add(1,11);
System.out.println(list);//[1, 11, 2, 3, 4, 5]
// list.remove(11);//此处默认将11当成下标来运算,而不是将11当成一个元素内容
list.remove(1);
System.out.println(list);//[1, 2, 3, 4, 5]
list.set(0,11);
System.out.println(list);//[11, 2, 3, 4, 5]
int a = list.get(0);
System.out.println(a);//11
list.add(5);
list.add(4);
list.add(3);
list.add(2);
list.add(11);
int b = list.indexOf(11);
System.out.println(b);//0
int c = list.lastIndexOf(11);
System.out.println(c);//9
List<Integer> list02 = new ArrayList<>();
list02.add(12);
list02.add(14);
list02.add(16);
list.addAll(1,list02);
System.out.println(list);//[11, 12, 14, 16, 2, 3, 4, 5, 5, 4, 3, 2, 11]
}
}
区分Collection接口中的remove方法、List接口中的remove方法
import java.util.ArrayList;
import java.util.List;
/**
* 区分Collection接口中的remove方法、List接口中的remove方法
*
*/
public class TestRemove {
public static void main(String[] args) {
List<String> list01 = new ArrayList<>();
list01.add("1");
list01.add("2");
list01.add("3");
list01.add("4");
list01.add("5");
System.out.println(list01);//[1, 2, 3, 4, 5]
//父接口Collection中的remove方法
list01.remove("1");
System.out.println(list01);//[2, 3, 4, 5]
//List接口中的remove方法
list01.remove(1);
System.out.println(list01);//[2, 4, 5]
System.out.println("=========================================");
List<Integer> list02 = new ArrayList<>();
list02.add(1);
list02.add(2);
list02.add(3);
list02.add(4);
list02.add(5);
list02.add(11);
list02.remove(1);
System.out.println(list02);//[1, 3, 4, 5, 11]
/**
* java.lang.IndexOutOfBoundsException: Index: 11, Size: 5
*/
list02.remove(11);//此处会报下表越界异常,因为在int类型中它默认指的是下标索引
}
}
练习一:手写模拟ArrayList创建数组,添加元素功能(加入泛型):
/**
* 手写ArrayList创建容器,添加元素功能
* 增加泛型
*/
public class WriteArrayList<E> {
private Object[] array;
private int size;//数组下标
private static final int DEFAULT = 10;
public WriteArrayList() {
array = new Object[DEFAULT];
}
public WriteArrayList(int index) {
array = new Object[index];
}
public void add(E data) {
array[size++] = data;
}
@Override
public String toString() {
//以[a,b,c]格式输出
StringBuilder sb = new StringBuilder();
sb.append("[");
for(int i=0; i<size; i++) {
sb.append(array[i]+",");
}
sb.setCharAt(sb.length()-1,']');//将最后输出的逗号','替换为']'符号,代码中的单引号不能更改为双引号
return sb.toString();
}
public static void main(String[] args) {
WriteArrayList<Integer> wal = new WriteArrayList<>();
wal.add(11);
wal.add(12);
wal.add(13);
System.out.println(wal);
}
}
练习二:在练习一的基础上增加数组扩容
/**
* 增加数组扩容
*/
public class WriteArrayList<E> {
private static Object[] array;
private int size;//数组下标
private static final int DEFAULT = 10;
public WriteArrayList() {
array = new Object[DEFAULT];
}
public WriteArrayList(int index) {
array = new Object[index];
}
public void add(E data) {
//什么时候扩容?
if(size==array.length) {
//如何扩容?
Object[] newArray = new Object[array.length+(array.length>>1)];//类比10+10/2,此处注意加号'+'优先级高于'>>'
System.arraycopy(array, 0, newArray, 0, array.length);
array = newArray;
}
array[size++] = data;
}
@Override
public String toString() {
//以[a,b,c]格式输出
StringBuilder sb = new StringBuilder();
sb.append("[");
for(int i=0; i<size; i++) {
sb.append(array[i]+",");
}
sb.setCharAt(sb.length()-1,']');//将最后输出的逗号','替换为']'符号,代码中的单引号不能更改为双引号
return sb.toString();
}
public static void main(String[] args) {
WriteArrayList<Integer> wal = new WriteArrayList<>();
for(int i=0; i<40; i++) {
wal.add(i);
}
System.out.println(wal);
}
}
练习三:在练习二的基础上增加set()、get()方法,增加数组边界检测
/**
* 增加set()、get()方法
* 增加数组边界检查(判断索引是否合法)
*/
public class WriteArrayList<E> {
private static Object[] array;
private int size;//数组下标
private static final int DEFAULT = 10;
public WriteArrayList() {
array = new Object[DEFAULT];
}
public WriteArrayList(int index) {
//加入判断
if(index<0) {
throw new RuntimeException("容器的容量不能为负数:"+index);
} else if(index==0) {
array = new Object[DEFAULT];
} else {
array = new Object[index];
}
}
public void add(E data) {
//什么时候扩容?
if(size==array.length) {
//如何扩容?
Object[] newArray = new Object[array.length+(array.length>>1)];//类比10+10/2,此处注意加号'+'优先级高于'>>'
System.arraycopy(array, 0, newArray, 0, array.length);
array = newArray;
}
array[size++] = data;
}
@Override
public String toString() {
//以[a,b,c]格式输出
StringBuilder sb = new StringBuilder();
sb.append("[");
for(int i=0; i<size; i++) {
sb.append(array[i]+",");
}
sb.setCharAt(sb.length()-1,']');//将最后输出的逗号','替换为']'符号,代码中的单引号不能更改为双引号
return sb.toString();
}
public E get(int index) {
checkIndex(index);
return (E)array[index];
}
public void set(int index, E data) {
checkIndex(index);
// //索引合法判断,索引区间应满足[0,size)
// if(index<0||index>size-1) {
// //不合法,手动抛出异常
// throw new RuntimeException("索引不合法:"+index);
// }
array[index] = data;
}
/**
* 由于许多地方都需要判断index索引是否合法,
* 所以在此处写一个独立的方法,需要时直接调用即可
*/
public void checkIndex(int index) {
//索引合法判断,索引区间应满足[0,size)
if(index<0||index>size-1) {
//不合法,手动抛出异常
throw new RuntimeException("索引不合法:"+index);
}
}
public static void main(String[] args) {
WriteArrayList<Integer> wal = new WriteArrayList<>();
for(int i=0; i<40; i++) {
wal.add(i);
}
System.out.println(wal.get(10));
wal.set(1,100);
System.out.println(wal);
}
}
练习四:在练习三的基础上增加remove()、size()、isEmpty()方法的实现
/**
* 增加2种remove()实现方法
* 增加size()、isEmpty()方法
*/
public class WriteArrayList<E> {
private static Object[] array;
private int size;//数组下标
private static final int DEFAULT = 10;
public WriteArrayList() {
array = new Object[DEFAULT];
}
public WriteArrayList(int index) {
//加入判断
if(index<0) {
throw new RuntimeException("容器的容量不能为负数:"+index);
} else if(index==0) {
array = new Object[DEFAULT];
} else {
array = new Object[index];
}
}
public void add(E data) {
//什么时候扩容?
if(size==array.length) {
//如何扩容?
Object[] newArray = new Object[array.length+(array.length>>1)];//类比10+10/2,此处注意加号'+'优先级高于'>>'
System.arraycopy(array, 0, newArray, 0, array.length);
array = newArray;
}
array[size++] = data;
}
@Override
public String toString() {
//以[a,b,c]格式输出
StringBuilder sb = new StringBuilder();
sb.append("[");
for(int i=0; i<size; i++) {
sb.append(array[i]+",");
}
sb.setCharAt(sb.length()-1,']');//将最后输出的逗号','替换为']'符号,代码中的单引号不能更改为双引号
return sb.toString();
}
public E get(int index) {
checkIndex(index);
return (E)array[index];
}
public void set(int index, E data) {
checkIndex(index);
// //索引合法判断,索引区间应满足[0,size)
// if(index<0||index>size-1) {
// //不合法,手动抛出异常
// throw new RuntimeException("索引不合法:"+index);
// }
array[index] = data;
}
/**
* 由于许多地方都需要判断index索引是否合法,
* 所以在此处写一个独立的方法,需要时直接调用即可
*/
public void checkIndex(int index) {
//索引合法判断,索引区间应满足[0,size)
if(index<0||index>size-1) {
//不合法,手动抛出异常
throw new RuntimeException("索引不合法:"+index);
}
}
public void remove(int index) {
//数组中需要移动的元素个数
int numMoved = array.length - index - 1;
if(numMoved>0) {
//底层原理:数组的拷贝
System.arraycopy(array, index+1, array, index, numMoved);
}
array[--size] = null;
}
public void remove(E data) {
for(int i=0; i<size; i++) {
if(array[i].equals(data)) {
remove(i);
}
}
}
public int size() {
return size;
}
public boolean isEmpty() {
return size==0?true:false;
}
public static void main(String[] args) {
WriteArrayList<Integer> wal = new WriteArrayList<>();
for(int i=0; i<40; i++) {
wal.add(i);
}
System.out.println(wal.get(10));
wal.set(1,100);
System.out.println(wal);
wal.remove(2);
System.out.println(wal);
WriteArrayList<String> s = new WriteArrayList<String>();
s.add("A");
s.add("B");
s.add("C");
s.add("D");
System.out.println(s);
s.remove(1);
System.out.println(s);
s.remove("D");
System.out.println(s);
System.out.println(s.size());
System.out.println(s.isEmpty());
}
}
学习StringBuilder类,及它提供的append()、setCharAt()方法
掌握数组拷贝arraycopy()方法:
System.arraycopy(被复制的数组, 从第几个元素开始复制, 要复制到哪个数组, 粘贴到什么位置, 一共要复制多少个元素);
自己独立重写ArrayList实现类的功能
练习1到4心得:
下面的代码是我独立完成的,与练习4的代码的本质区别是:size和array.length具体代表的含义。
我下面的代码中size代表容器中元素的个数,array.length表示容器大小,由于数组扩容,容器大小一般大于元素个数。
注意==与equals的区别。
public class WriteArrayList02<E> {
private Object[] array;
private int size;
private static final int DEFAULT = 10;
public WriteArrayList02() {
array = new Object[DEFAULT];
}
public WriteArrayList02(int index) {
if(index == 0) {
array = new Object[DEFAULT];
}else if(index<0) {
throw new RuntimeException("索引不能为负数:"+index);
}else {
array = new Object[index];
}
}
public void add(E element) {
if(size==array.length) {
Object[] newArray = new Object[array.length+(array.length>>1)];
System.arraycopy(array, 0, newArray, 0, array.length);
array = newArray;
}
array[size++] = element;
}
public void set(int index, E element) {
checkIndex(index);
array[index] = element;
}
public E get(int index) {
checkIndex(index);
return (E)array[index];
}
public void checkIndex(int index) {
if(index<0||index>=size) {
throw new RuntimeException("索引异常:"+index);
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("[");
for(int i=0; i<size; i++) {
sb.append(array[i]+",");
}
sb.setCharAt(sb.length()-1,']');
return sb.toString();
}
public void remove(E element) {
for(int i=0; i<size; i++) {
if(array[i].equals(element)) {
remove(i);
}
}
}
public void remove(int index) {
System.out.println(array.length);
//1,2,3,4,5,6,7
int numCopy = size - index - 1;
if(numCopy<0) {
throw new RuntimeException("索引异常:"+index);
}else if(numCopy==0) {
array[size] = null;
}else {
System.arraycopy(array, index+1, array, index, numCopy);
}
//array[size-1] = null;
size--;
System.out.println(array.length);
}
public int size() {
return size;
}
public boolean isEmpty() {
return size==0?true:false;
}
public static void main(String[] args) {
WriteArrayList02<String> wal = new WriteArrayList02<>();
for(int i=0; i<40; i++) {
wal.add(i+"");
}
System.out.println(wal);
wal.set(1,"11");
System.out.println(wal);
System.out.println(wal.get(39));
wal.set(39,"12");
System.out.println(wal);
wal.remove(0);
System.out.println(wal);
// wal.remove(38);
// System.out.println(wal);
wal.remove("12");
System.out.println(wal);
System.out.println(wal.size());
System.out.println(wal.isEmpty());
}
}
LinkedList链表存储结构
最后
感谢你看到这里,看完有什么的不懂的可以在评论区问我,觉得文章对你有帮助的话记得给我点个赞,每天都会分享java相关技术文章或行业资讯,欢迎大家关注和转发文章!