Collection集合
集合:集合是Java中提供的一种容器,可以用来存储多个数据
集合和数组都是容器,但是两者有较大的区别:
- 数组的长度是固定的,而集合的长度是可以变的
- 数组中存储的是同一类型的数据,可以存储基本数据类型;集合存储的都是对象,而对象的类型可以不一致,当对象过多的时候就是用集合来进行存储
集合框架
集合按照存储结构可以分为两大类,单列集合java.util.Collection
和双列集合java.util.Map
- Collection:单列集合类的根接口,用于存储一系列符合某种规律的元素,有List和Set两个重要的子接口;
List
的特点是元素有序、元素可重复- 主要实现类:
java.util.ArrayList
和java.util.LinkedList
- 主要实现类:
Set
的特点是元素无须、且不可重复- 主要实现类:
java.util.HashSet
和java.util.TreeSet
- 主要实现类:
Collcetion集合当中的常用方法:
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()
: 把集合中的元素,存储到数组中。
Collection<String> coll = new ArrayList<String>();
coll.add("你好");
//利用对象名.方法名来调用,比较简单,不一一举例
Iterator迭代器
java.util.Iterator
。Iterator
接口也是Java集合中的一员,但它与Collection
、Map
接口有所不同,Collection
接口与Map
接口主要用于存储元素,而Iterator
主要用于迭代访问(即遍历)Collection
中的元素,因此Iterator
对象也被称为迭代器。
public Iterator iterator()
: 获取集合对应的迭代器,用来遍历集合中的元素的。
迭代:在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来。然后继续判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。
常用方法:
public E next()
:返回迭代的下一个元素。public boolean hasNext()
:如果仍有元素可以迭代,则返回 true。
Iterator迭代器是一个接口,无法直接使用,需要使用Iterator接口的实现类对象来获取。Collection接口中有一个方法叫做Iterator(),这个方法返回的就是迭代器的实现类对象
迭代器的使用步骤:
- 使用集合中的Iterator()方法获取迭代器的实现类对象
- 用hasNext()进行判断是否有下一个元素
- 使用next()取出集合中的下一个元素
package Demo04;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class DemoIterator {
public static void main(String[] args) {
Collection<String> coll = new ArrayList<String>();
coll.add("科比");
coll.add("库里");
coll.add("詹姆斯");
coll.add("杜兰特");
coll.add("欧文");
Iterator<String> it = coll.iterator(); //使用集合中的Iterator()方法获取迭代器的实现类对象
while (it.hasNext()){ //用hasNext()进行判断是否有下一个元素
System.out.println(it.next()); //使用next()取出集合中的下一个元素
}
}
}
增强for循环
高级for循环,专门用来遍历数组和集合,他的内部原理其实是一个迭代器(简化迭代器的写法),所以在便利的过程中,不能对集合中的元素进行增删改查
格式:
for(集合/数组的数据类型 变量名 : Collection集合名or数组名){
//写操作代码
}
示例:
package Demo04;
import java.util.ArrayList;
import java.util.Collection;
public class DemoFor {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
for (int i:arr) {
System.out.println(i);
}
Collection<String> coll = new ArrayList<String>();
coll.add("aaa");
coll.add("bbb");
coll.add("ccc");
coll.add("ddd");
coll.add("eee");
for (String s:coll) {
System.out.println(s);
}
}
}
泛型
泛型的好处
- 在创建集合对象的时候,不使用泛型:
好处:集合不使用泛型,默认的类型就是Object类型,可以存储任意类型的数据
坏处:不安全,会引发异常
package Demo04;
import java.sql.SQLOutput;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Objects;
public class DemoFanXing {
public static void main(String[] args) {
show01();
}
private static void show01() {
ArrayList list = new ArrayList();
list.add("abc");
list.add(1);
Iterator it = list.iterator();
while(it.hasNext()){
Object obj = it.next();
System.out.println(obj);
String s = (String)obj;
System.out.println(s.length());
/*
abc
3
1
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
抛出异常,Integer类型不能转换为String类型,所以不安全
*/
}
}
}
- 在创建对象时,使用泛型:
好处:避免了类型转换的麻烦,存什么类型,就取什么类型;把运行期异常(代码运行后会抛出异常)转换为编译期异常(写代码时就会报错)
坏处:泛型是什么类型,就只能存什么样的数据,类型固定
package Demo04;
import java.sql.SQLOutput;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Objects;
public class DemoFanXing {
public static void main(String[] args) {
show02();
}
private static void show02() {
ArrayList<String> list = new ArrayList<String>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
list.add("eee");
//list.add(1); 在编写代码的时候就会有红色的下划线报错,不能存入整数
Iterator<String> it = list.iterator();
while(it.hasNext()){
System.out.println(it.next());
System.out.println(it.next().length()); //可以直接用String类型的方法,就不用进行类型的转换,从而避免了类型转换时出现的错误
}
}
}
泛型的定义与使用
定义和使用含有泛型的类:
定义格式:修饰符 class 类名<代表泛型的变量> { }
注意:创建对象的时候,就确定泛型的数据类型
//不使用泛型的DemoGeneric类
package Demo04;
public class DemoGeneric {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
//主函数
package Demo04;
public class DemoGenericTest {
public static void main(String[] args) {
DemoGeneric gc = new DemoGeneric();
gc.setName("库里"); //DemoGeneric类中是private String name,所以只能set一个字符串类型的数据
//gc.setName(1);这个就会出错,不能放入整数类型的数据
System.out.println(gc.getName()); //返回也只能返回字符串类型的数据
}
}
//使用泛型的DemoGeneric类
package Demo04;
/*
定义一个含有泛型的类
泛型是一个未知的数据类型,当我们不确定什么数据类型的时候,可以使用泛型
泛型可以接受任意的数据类型,可以使用Integer、String、Student等等
创建对象的时候,就确定泛型的数据类型
*/
public class DemoGeneric<E> { //定义一个泛型的类
private E name;
public E getName() {
return name;
}
public void setName(E name) {
this.name = name;
}
}
//主函数
package Demo04;
public class DemoGenericTest {
public static void main(String[] args) {
DemoGeneric<Integer> gc = new DemoGeneric();
gc.setName(1);
//创建对象的时候,就确定泛型的数据类型,其中能够加入什么类型的数据,就是跟着< >中的类型来判断的
DemoGeneric<String> gc1 = new DemoGeneric<>();
gc1.setName("库里");
}
}
定义和使用含有泛型的方法:
定义格式:修饰符 <代表泛型的变量> 返回值类型 方法名(参数){方法体}
注意:调用方法的时候确定泛型的数据类型
//含有泛型的静态方法
package Demo04;
import java.lang.reflect.Type;
/*
定义含有泛型的方法:泛型定义方法在方法的修饰符和返回值之间
含有泛型的方法,在调用方法的时候确定泛型的数据类型
传递什么类型,就是什么类型
*/
public class DemoGenericMethod {
public <M> void method01(M m){
System.out.println(m);
}
//含有泛型的静态方法
public static <E> void method02(E m){
System.out.println(m);
}
}
//主函数
package Demo04;
public class DemoGenericMethodTest {
public static void main(String[] args) {
DemoGenericMethod gm = new DemoGenericMethod();
gm.method01(1);
gm.method01("abc");
gm.method01(3.1415926);
gm.method01(true); //传入什么类型就是什么类型的数据
gm.method02("不建议");
gm.method02(1);
}
}
含有泛型的接口:
格式:修饰符 interface接口名<代表泛型的变量> { }
//定义接口
package Demo04;
public interface DemoGenericInterface<I> {
public abstract void method(I i);
}
package Demo04;
/*
含有泛型的接口:
第一种使用方式:定义接口的实现类,实现接口,指定接口的泛型
*/
public class GenericInterfaceImpl01 implements DemoGenericInterface<String>{
@Override
public void method(String s) {
System.out.println(s);
}
}
//主函数
package Demo04;
public class GenericInterface {
public static void main(String[] args) {
GenericInterfaceImpl01 gi1 = new GenericInterfaceImpl01();
gi1.method("abc"); //abc
}
}
//定义接口
package Demo04;
public interface DemoGenericInterface<I> {
public abstract void method(I i);
}
package Demo04;
/*
含有泛型的接口:
第二种使用方式:接口什么类型,实现类就用什么类型,类跟着接口走
*/
public class GenericInterfaceImpl02<E> implements DemoGenericInterface<E>{
@Override
public void method(E e) {
System.out.println("02"+e);
}
}
//主函数
package Demo04;
public class GenericInterface {
public static void main(String[] args) {
GenericInterfaceImpl01<String> gi2 = new GenericInterfaceImpl01<>();
gi1.method("abc"); //02abc
}
}
泛型通配符
当使用泛型类或者接口时,传递的数据中,泛型类型不确定,可以通过**通配符<?>**表示。但是一旦使用泛型的通配符后,只能使用Object类中的共性方法,集合中元素自身方法无法使用
package Demo04.Generic;
import java.util.ArrayList;
import java.util.Iterator;
/*
泛型的通配符:
?代表任意的数据类型
使用方式:
不能创建对象使用
只能作为方法的参数使用
*/
public class DemoTong {
public static void main(String[] args) {
ArrayList<Integer> list01 = new ArrayList<>();
list01.add(1);
list01.add(2);
ArrayList<String> list02 = new ArrayList<>();
list02.add("a");
list02.add("b");
print(list01);
print(list02);
}
/*
定义一个方法,能够遍历所有类型的ArrayList集合
但是这个时候我们不知道ArrayList集合使用说明数据类型,就可以使用泛型通配符?
*/
public static void print(ArrayList<?> list){ //可以接受任意的数据类型
Iterator<?> it = list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
受限泛型:
之前设置泛型的时候,实际上是可以任意设置的,只要是类就可以设置。但是在JAVA的泛型中可以指定一个泛型的上限和下限。
泛型的上限:
- 格式:
类型名称 <? extends 类 > 对象名称
- 意义:
只能接收该类型及其子类
泛型的下限:
- 格式:
类型名称 <? super 类 > 对象名称
- 意义:
只能接收该类型及其父类型
比如:现已知Object类,String 类,Number类,Integer类,其中Number是Integer的父类
package Demo04.Generic;
import java.util.ArrayList;
public class DemoTongXianZhi {
public static void main(String[] args) {
ArrayList<Integer> list1 = new ArrayList<Integer>();
ArrayList<String> list2 = new ArrayList<String>();
ArrayList<Number> list3 = new ArrayList<Number>();
ArrayList<Object> list4 = new ArrayList<Object>();
print1(list1);
print1(list2);//报错
print1(list3);
print1(list4);//报错
print2(list1);//报错
print2(list2);//报错
print2(list3);
print2(list4);
}
// 泛型的上限:此时的泛型?,必须是Number类型或者Number类型的子类
public static void print1(ArrayList<? extends Number> list){}
// 泛型的下限:此时的泛型?,必须是Number类型或者Number类型的父类
public static void print2(ArrayList<? super Number> list){}
}