文章目录
Collection、Iterator、泛型
一、Collection集合
1. Collection集合概述
- **集合:**集合是
Java
中提供的一种容器,可以用来存储多个数据。 - 集合与数组的区别:
- 数组的长度是固定的,集合的长度是可变的。
- 数组中存储的是同一类型的元素,可以存储基本数据类型和对象。集合存储的都是对象,而且对象的类型可以不一致。
2. 集合框架介绍
- ArrayList(重点):底层是数组实现的,查询快,增删慢。
- LinkedList(次之):底层是链表实现的,查询慢,增删快。
- Vector(了解)
- HashSet(重点):底层是哈希表+(红黑树)实现的,无索引,不可以存储重复元素,存取无序。
- **LinkedHashSet(次之):**底层是哈希表+链表实现的,无索引,不可以存储重复元素,可以保证存储顺序。
- **TreeSet(了解):**底层是二叉树实现,一般用于排序。
3. Collection集合常用方法
-
java.util.Collection
接口:所有单列集合的最顶层接口,里边定义了单列集合共性的方法,任意的单列集合都可以使用Collection
接口中的方法。 -
boolean add(E e);
向集合中添加元素 -
boolean remove(E e);
删除集合中某个元素 -
void clear();
清空集合所有的元素 -
boolean contains(E e);
判断集合中是否包含某个元素 -
boolean isEmpty();
判断集合是否为空 -
int size();
获取集合的长度 -
Object[] toArray();
将集合转为一个数组
import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;
public class Test {
public static void main(String[] args) {
Collection<String> coll = new ArrayList<>();
//boolean add(E e); 向集合中添加元素
coll.add("Hello");
coll.add("World");
coll.add("zhu");
coll.add("gu");
coll.add("li");
System.out.println(coll); // [Hello, World, zhu, gu, li]
//boolean remove(E e); 删除集合中某个元素
/*coll.remove("Hello");
coll.remove("World");
System.out.println(coll); */ // [zhu, gu, li]
//void clear(); 清空集合所有的元素
/*coll.clear();
System.out.println(coll);*/ // []
//boolean contains(E e); 判断集合中是否包含某个元素
/*boolean bool1 = coll.contains("Hello");
System.out.println(bool1); // true
boolean bool2 = coll.contains("world");
System.out.println(bool2); */ // false
// boolean isEmpty(); 判断集合是否为空
/*boolean bool3 = coll.isEmpty();
System.out.println(bool3); // false
coll.clear();
boolean bool4 = coll.isEmpty();
System.out.println(bool4); */ // true
// int size(); 获取集合的长度
/*int len = coll.size();
System.out.println(len);*/ // 5
//Object[] toArray(); 将集合转为一个数组
/*Object[] strings = coll.toArray();
for (int i = 0; i < strings.length; i++) {
System.out.println(strings[i]);
}*/
}
}
二、Iterator迭代器
1. Iterator接口介绍
java.util.Iterator
接口:迭代器(对集合进行遍历)。- 两个常用方法:
boolean hasNext()
:判断集合中还有没有下一个元素,有就返回true
,没有就返回false
。E next()
:返回迭代的下一个元素(取出集合中的下一个元素)。
Iterator
迭代器,是一个接口,无法直接使用,需要使用Iterator
接口的实现类对象,获取实现类对象的方式为:Collection
接口中有一个方法,为iterator()
,这个方法返回的就是迭代器的实现类对象。Iterator<E> iterator()
返回在此Collection
的元素上进行迭代的迭代器。
- 迭代器的使用步骤:
- 使用集合中的方法
iterator()
获取迭代器的实现类对象,使用Iterator
接口接收(多态)。 - 使用
Iterator
接口中的方法hasNext()
判断还有没有下一个元素。 - 使用
Iterator
接口中的方法next()
取出集合中的下一个元素。
- 使用集合中的方法
2. 迭代器的代码实现
Iterator<E>
也是有泛型的,迭代器的泛型与集合的泛型一致。- 若已没有下一个元素,再次取出时会抛出
NoSuchElementException
没有元素异常。
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class Test {
public static void main(String[] args) {
Collection<String> coll = new ArrayList<>();
coll.add("朱古力");
coll.add("猪猪侠");
coll.add("猪猪猪");
Iterator<String> it = coll.iterator();
while (it.hasNext()) {
System.out.println(it.next()); // 朱古力
} // 猪猪侠
} // 猪猪猪
}
3. 迭代器的实现原理
iterator()
获取迭代器的实现类对象,并且把指针(索引)指向集合的-1索引。hasNext()
判断集合中还有没有下一个元素。next()
先取出下一个元素,再把指针向后移动一位。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UBoIZHD8-1589460905495)(https://raw.githubusercontent.com/zhugulii/picBed/master/02_%E8%BF%AD%E4%BB%A3%E5%99%A8%E7%9A%84%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86(1)].bmp)
4. 增强for
循环
- 底层使用的也是迭代器,使用
for
循环的格式,简化了迭代器的代码。 - 是
JDK1.5
之后出现的新特性。 Collection<E> extends Iterable<E>
所有的单列集合都可以使用增强for
public interface Iterabel<T>
实现这个接口允许对象成为foreach
语句的目标。- 增强
for
循环:用来遍历集合和数组。
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
ArrayList<String> strings = new ArrayList<>();
strings.add("朱古力");
strings.add("猪猪侠");
strings.add("猪猪猪");
for (String str : strings) {
System.out.println(str); // 朱古力
// 猪猪侠
// 猪猪猪
}
}
}
三、泛型
1. 泛型的概念
- **泛型:**是一种未知的数据类型,当我们不知道使用什么数据类型的时候可以使用泛型。
- 泛型也可以看做是一个变量,用来接收数据类型。
E e
:Element元素T t
:Type类型
2. 使用泛型的好处
-
创建集合对象,不使用泛型
- 好处:集合不适用泛型,默认的类型的就是
Object
类型,可以存储任意类型的数据。 - 弊端:不安全会引发异常。
import java.util.ArrayList; import java.util.Iterator; public class Test01 { public static void main(String[] args) { ArrayList list = new ArrayList(); list.add("zhuguil"); list.add(123); Iterator it = list.iterator(); /*while (it.hasNext()) { System.out.println(it.next()); // zhuguli 123 }*/ while (it.hasNext()) { String s = (String) it.next(); System.out.println(s.length()); // 会引发异常 Integer不能转换为String类型 } } }
- 好处:集合不适用泛型,默认的类型的就是
-
创建集合对象,使用泛型
- 好处:
- 避免了类型转换的麻烦,存储的是什么类型,取出的就是什么类型。
- 把运行期异常 (代码运行之后会抛出的异常),提升到了编译期 (写代码的时候会报错)。
- 弊端:泛型是什么类型,就只能存储什么类型的数据。
import java.util.ArrayList; import java.util.Iterator; public class Test02 { public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); list.add("zhuguli"); list.add("zhuzhuxia"); list.add("zhuzhuzhuzhu"); Iterator<String> it = list.iterator(); while (it.hasNext()) { String str = it.next(); System.out.println(str + " 长度为:" + str.length()); // zhuguli 长度为:7 // zhuzhuxia 长度为:9 // zhuzhuzhuzhu 长度为:12 } } }
- 好处:
3. 定义和使用含有泛型的类
- 定义格式:
修饰符 class 类名<代表泛型的变量> {...}
。
public class TestGenericClass {
public static void main(String[] args) {
GenericClass<String> gc1 = new GenericClass<>();
gc1.setName("zhuzhuzhu");
System.out.println(gc1.getName()); // zhuzhuzhu
GenericClass<Integer> gc2 = new GenericClass<>();
gc2.setName(111);
System.out.println(gc2.getName()); // 111
}
}
4. 定义和使用含有泛型的方法
-
定义含有泛型的方法:泛型定义在方法的修饰符合返回值类型之间。
-
格式:
修饰符 <泛型> 返回值类型 方法名(参数列表(使用泛型)) { //方法体 }
- 含有泛型的方法,在调用方法的时候确定泛型的数据类型。
- 传递什么类型的参数,泛型就是什么类型。
-
定义含有泛型的静态方法
-
格式:
修饰符 static <泛型> 返回值类型 方法名(参数列表(使用泛型)) { //方法体 }
public class GenericMethod {
public <E> void method_01(E e) {
System.out.println(e);
}
public static <E> void method_02(E e) {
System.out.println(e);
}
}
public class TestGenericMethod {
public static void main(String[] args) {
GenericMethod gc = new GenericMethod();
gc.method_01("zhuguli"); // zhuguli
gc.method_01(111); // 111
GenericMethod.method_02("zhuzhuxia"); // zhuzhuxia
GenericMethod.method_02(222); // 222
}
}
5. 定义和使用含有泛型的接口
-
定义格式:
修饰符 interface 接口名<代表参数的变量> {...}
-
使用的两种方式:
-
定义接口的实现类,指定接口的泛型
public interface GenericInterface<E> { public abstract void method(); } public class GenericInterfaceImpl<String> implements GenericInterface<String>{ @Override public void method() { System.out.println("HelloWorld!"); } } public class TestGenericInterfaceImpl { public static void main(String[] args) { GenericInterfaceImpl gc = new GenericInterfaceImpl(); gc.method(); // HelloWorld! } }
-
接口使用什么泛型,实现类就使用什么泛型,相当于定义了一个含有泛型的类,创建对象的时候确定泛型的类型。
public interface GenericInterface<E> { public abstract void method(); } public class GenericInterfaceImpl2<E> implements GenericInterface<E> { @Override public void method() { System.out.println("HelloWorld! "); } } public class TestGenericInterfaceImpl2 { public static void main(String[] args) { GenericInterfaceImpl2<String> gc = new GenericInterfaceImpl2<>(); gc.method(); // HelloWorld! } }
-
6. 泛型通配符
- 泛型的通配符:
?
代表任意的数据类型。 - 使用方式:不能创建对象使用,只能作为方法的参数使用。
- 注意:泛型没有继承的概念。
import java.util.ArrayList;
import java.util.Iterator;
public class Test {
public static void main(String[] args) {
ArrayList<Integer> list01 = new ArrayList<>();
list01.add(1);
list01.add(2);
list01.add(3);
ArrayList<String> list02 = new ArrayList<>();
list02.add("朱古力");
list02.add("猪猪侠");
list02.add("猪猪猪");
printArray(list01); // 1 2 3
printArray(list02); // 朱古力 猪猪侠 猪猪猪
}
public static void printArray(ArrayList<?> arrayList){
Iterator<?> it = arrayList.iterator();
while (it.hasNext()) {
Object obj = it.next();
System.out.println(obj);
}
}
}
- 泛型的上限限定:
? extends E
代表使用的泛型只能是E
类型的子类/本身。 - 泛型的下限限定:
? super E
代表使用的泛型只能是E
类型的父类/本身。