1. 集合概述
java.util.Collection
集合也是一种容器,与数组的区别:
- 数组:长度固定,数据类型一致
- 集合:存储的为对象,对象类型可不一致,长度也不固定,比较常用
Collection 按存储结构分类
- 单列集合类
java.util.Collection
:它有两个重要的子接口:java.util.List、java.util.Set
List
:元素有序、元素可重复Set
:无序,不可重复
- 双列集合
java.util.Map
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-49KOKkhL-1673620095039)(https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg-blog.csdnimg.cn%2F20190926201633911.png%3Fx-oss-process%3Dimage%2Fwatermark%2Ctype_ZmFuZ3poZW5naGVpdGk%2Cshadow_10%2Ctext_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MjU0MTI1NA%3D%3D%2Csize_16%2Ccolor_FFFFFF%2Ct_70&refer=http%3A%2F%2Fimg-blog.csdnimg.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1652778572&t=175a3828bfd97568fe0773ece7688767)]
1.1 集合常用功能
下面是一些单列集合通用的方法:
public boolean add(E e)
: 把给定的对象添加到当前集合中public void clear()
:清空集合中所有的元素public boolean remove(E e)
:把给定的对象在当前集合中删除public boolean contains(E e)
: 判断当前集合中是否包含给定的对象public boolean isEmpty()
:判断当前集合是否为空public int size()
:返回集合中元素的个数public Object[] toArray()
: 把集合中的元素,存储到数组中
import java.util.ArrayList;
import java.util.Collection;
public class CollectionSingle {
public static void main(String[] args) {
Collection<String> coll = new ArrayList<>();
coll.add("张三");
coll.add("李四");
System.out.println(coll.contains("张三"));
System.out.println(coll.size());
System.out.println(coll.isEmpty());
coll.remove("李四");
// 转换为数组
Object[] object = coll.toArray();
for (int i = 0; i < object.length; i++) {
System.out.println(object[i]);
}
coll.clear();
}
}
2. Iterator 迭代器
java.util.Iterator
迭代器用于遍历集合元素,它有两个方法:
next()
:获取下一个元素hasNext()
:判断是否还有下一个元素,使用时先判断是否有下一个元素,以防出现java.util.NoSuchElementException
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class IteratorDemo {
public static void main(String[] args) {
Collection<String> coll = new ArrayList<String>();
coll.add("rose");
coll.add("lila");
coll.add("john");
Iterator<String> iterator = coll.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
2.1 增强型 for 循环
增强for
循环(也称for each
循环),专门用来遍历数组和集合的。它的内部原理其实是个Iterator
迭代器,所以在遍历的过程中,不能对集合中的元素进行增删操作
格式:
for(元素的数据类型 变量 : Collection集合or数组){
//写操作代码
}
示例:
public class IteratorDemo {
public static void main(String[] args) {
Collection<String> coll = new ArrayList<String>();
coll.add("rose");
coll.add("lila");
coll.add("john");
for (String s: coll) {
System.out.println(s);
}
}
}
3. 泛型
3.1 泛型的好处
集合可以存储任意对象,只要将对象存储到集合后,就会自动提升为 Object
类型。当取出对象并做相应操作,就必须类型转换:
public class GenericDemo {
public static void main(String[] args) {
Collection coll = new ArrayList();
coll.add("rose");
coll.add("lila");
coll.add(5);
Iterator iterator = coll.iterator();
while (iterator.hasNext()) {
// 强制为 String 类型,引发 java.lang.ClassCastException
String str = (String) iterator.next();
System.out.println(str);
}
}
}
通常Collection
只存储同一类型对象。例如都是存储字符串对象。因此在JDK5之后,新增了泛型(Generic)语法,让你在设计API时可以指定类或方法支持泛型,这样我们使用API
的时候也变得更为简洁,并得到了编译时期的语法检查
泛型的好处
- 将运行时期的
ClassCastException
转移到编译时期变成编译失败 - 避免类型强制麻烦,提升性能(遍历时,由于返回类型为
Object
,如果要使用子类特有方法或属性,需要向下转型) - 对集合中的
ArrayList
的数据类型进行约束
public class GenericDemo {
public static void main(String[] args) {
Collection<String> coll = new ArrayList<String>();
coll.add("rose");
coll.add("lila");
// coll.add(5); //当集合明确类型后,存放类型不一致就会编译报错
// 集合已经明确具体存放的元素类型,那么在使用迭代器的时候,迭代器也同样会知道具体遍历元素类型
Iterator<String> iterator = coll.iterator();
while (iterator.hasNext()) {
String str = iterator.next();
System.out.println(str);
}
}
}
3.2 泛型的定义及使用
泛型,用来灵活地将数据类型应用到不同的类、方法、接口当中。将数据类型作为参数进行传递
3.2.1 定义和使用含有泛型的类
格式:
修饰符 class 类名<代表泛型的变量> { }
示例:
// 自定义泛型类
public class GenericClassDemo {
public static void main(String[] args) {
// 创建一个泛型为 String 类型的类
MyGenericMVP<String> my = new MyGenericMVP<String>();
my.setMVP("rose");
System.out.println(my.getMVP());
// 定义一个泛型为 Int 类型的类
MyGenericMVP<Integer> my1 = new MyGenericMVP<Integer>();
my1.setMVP(1);
System.out.println(my1.getMVP());
}
}
// MVP 不知道的数据类型
class MyGenericMVP<MVP> {
private MVP mvp;
public void setMVP(MVP mvp) {
this.mvp = mvp;
}
public MVP getMVP() {
return mvp;
}
}
3.2.2 含有泛型的方法
格式:
修饰符 <代表泛型的变量> 返回值类型 方法名(参数){ }
示例:
使用格式:调用方法时,确定泛型的类型
public class MyGenericMethod {
public static void main(String[] args) {
GenericMethodDemo mm = new GenericMethodDemo();
mm.show("aaa");
mm.show(123);
System.out.println(mm.show2(1234));
}
}
class GenericMethodDemo {
public <MVP> void show(MVP mvp) {
System.out.println(mvp.getClass());
}
public <MVP> MVP show2(MVP mvp) {
return mvp;
}
}
3.2.3 含有泛型的接口
定义格式:
修饰符 interface接口名<代表泛型的变量> { }
示例:
interface GenericInterface<E> {
public abstract void add(E e);
public abstract E getE();
}
1、 定义类时确定泛型类型
// 此时泛型 E 的值就是 String 类型
class MyImp1 implements GenericInterface<String> {
@Override
public void add(String e) {
}
@Override
public String getE() {
return null;
}
}
2、使用时确定泛型类型
class MyImp2<E> implements GenericInterface<E> {
@Override
public void add(E e) {
}
@Override
public E getE() {
return null;
}
}
使用:
public class MyGenericInterface {
public static void main(String[] args) {
MyImp2<String> my = new MyImp2<String>();
my.add("aa");
}
}
3.3 泛型通配符
当使用泛型类或者接口时,传递的数据中,泛型类型不确定,可以通过通配符<?>
表示。但是一旦使用泛型的通配符后,只能使用Object
类中的共性方法,集合中元素自身方法无法使用
public class MyGenericInterface {
public static void main(String[] args) {
// 泛型通配符
Collection<String> coll1 = new ArrayList<String>();
getElement(coll1);
Collection<Integer> coll2 = new ArrayList<Integer>();
getElement(coll2);
}
// 泛型通配符,可接收任意类型
public static void getElement(Collection<?> coll) {}
}
注意:泛型不存在继承关系
Collection<Object> list = new ArrayList<String>();
这种是错误的
3.3.1 通配符高级使用----受限泛型
之前设置泛型的时候,实际上是可以任意设置的,只要是类就可以设置。但是在JAVA的泛型中可以指定一个泛型的上限和下限。
泛型的上限:
- 格式:
类型名称 <? extends 类 > 对象名称
- 意义:
只能接收该类型及其子类
泛型的下限:
- 格式:
类型名称 <? super 类 > 对象名称
- 意义:
只能接收该类型及其父类型
比如:现已知Object
类,String
类,Number
类,Integer
类,其中Number
是Integer
的父类:
public static void main(String[] args) {
Collection<Integer> list1 = new ArrayList<Integer>();
Collection<String> list2 = new ArrayList<String>();
Collection<Number> list3 = new ArrayList<Number>();
Collection<Object> list4 = new ArrayList<Object>();
getElement(list1);
getElement(list2);//报错
getElement(list3);
getElement(list4);//报错
getElement2(list1);//报错
getElement2(list2);//报错
getElement2(list3);
getElement2(list4);
}
// 泛型的上限:此时的泛型?,必须是Number类型或者Number类型的子类
public static void getElement1(Collection<? extends Number> coll){}
// 泛型的下限:此时的泛型?,必须是Number类型或者Number类型的父类
public static void getElement2(Collection<? super Number> coll){}