迭代器Iterator
迭代器Iterator是JDK提供的一种访问Collection接口(Set,List,Map)的工具,下面我们看Iterator接口的源码:
public interface Iterator<E> {
/**
* Returns {@code true} if the iteration has more elements.
* (In other words, returns {@code true} if {@link #next} would
* return an element rather than throwing an exception.)
*
* @return {@code true} if the iteration has more elements
*/
boolean hasNext();
/**
* Returns the next element in the iteration.
*
* @return the next element in the iteration
* @throws NoSuchElementException if the iteration has no more elements
*/
E next();
......
}
其中 boolean hasNext(); 方法就是判断有没有下一个数据对象, E next(); 是一个指针,每遍历一次都指向当前数据对象。
其实,Collection接口的底层早已实现了Iterator接口,用List和Arraylist举例:
首先进入List接口源码,看见list继承了Collection接口:
public interface List<E> extends Collection<E> {}
进入Collection接口源码,看到Collection接口继承了Iterable接口:
public interface Collection<E> extends Iterable<E> {}
进入Iterable接口源码,看见Iterable接口里面定义了一个Iterator对象iterator,获得迭代器对象
public interface Iterable<T> {
/**
* Returns an iterator over elements of type {@code T}.
*
* @return an Iterator.
*/
Iterator<T> iterator();
......
}
捋一下思路:Collection接口继承Iterable接口,Iterable接口里面把Iterator类实例化获得迭代器Iterator对象和方法。
下面使用迭代器Iterator来遍历ArrayList容器:
package myinterator;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
* 测试迭代器Iterator遍历ArrayList容器
*
* @author 发达的范
* @date 2020/11/19 19:45
*/
public class TestIterator {
public static void main(String[] args) {
testIterator();
}
public static void testIterator() {
List<String> list = new ArrayList<>();
list.add("qqq");
list.add("www");
list.add("eee");
System.out.println(list);
//这里在for循环里面定义了一个接口对象,就类似于int i=0;注意后面不需要加i++
for (Iterator<String> iterator = list.iterator(); iterator.hasNext(); ) {
//iterator.next()既返回了当前的对象,也使游标向后移动并指向下一个数据对象
String temp = iterator.next();
System.out.println(temp);
}
}
}
运行结果:
使用迭代器Iterator遍历Set容器也使类似:
public static void testIteratorSet() {
Set<String> stringSet = new HashSet<>();
stringSet.add("rrr");
stringSet.add("ttt");
stringSet.add("yyy");
System.out.println(stringSet);
for (Iterator<String> stringIterator = stringSet.iterator(); stringIterator.hasNext();) {
String string = stringIterator.next();
System.out.println(string);
}
}
运行结果:
使用迭代器Iterator遍历Map容器有所区别:
public static void testIteratorMap01() {//遍历HashMap方法一
Map<Integer, String> stringMap = new HashMap<>();
stringMap.put(001,"uuu");
stringMap.put(002,"iii");
stringMap.put(003,"ooo");
System.out.println(stringMap);
Set<Map.Entry<Integer,String>> set=stringMap.entrySet();//Set获取stringMap中键值对的集合
for (Iterator<Map.Entry<Integer, String>> iterator = set.iterator(); iterator.hasNext();) {
Map.Entry<Integer,String> temp=iterator.next();
System.out.println(temp);
}
/*//另一种写法,获取迭代器的时候不加泛型,遍历数据的时候强制转型
for (Iterator iterator = set.iterator(); iterator.hasNext();) {
Map.Entry<Integer,String> temp=(Map.Entry<Integer, String>) iterator.next();
System.out.println(temp);
}*/
Set<Map.Entry<Integer, String>> set1 = stringMap.entrySet();//借助Set接口,把所有的键值对放入Set集合中
//Set集合中有Iterator方法,获取所有键值对的迭代器
Iterator<Map.Entry<Integer, String>> iterator = set1.iterator();
while (iterator.hasNext()) {
Map.Entry<Integer, String> temp = iterator.next();
System.out.println(temp);
}
}
运行结果:
public static void testIteratorMap() {//遍历HashMap方法二
Map<Integer, String> stringMap = new HashMap<>();
stringMap.put(001,"ppp");
stringMap.put(002,"aaa");
stringMap.put(003,"sss");
System.out.println(stringMap);
Set<Integer> set = stringMap.keySet();//获得键的集合存在Set中
for (Iterator<Integer> integerIterator = set.iterator(); integerIterator.hasNext(); ) {
Integer key = integerIterator.next();
System.out.println(key+"--"+stringMap.get(key));
}
Set<Integer> set1 = stringMap.keySet();
Iterator<Integer> iterator = set1.iterator();//Set集合中有Iterator方法,获取所有键的迭代器
while (iterator.hasNext()) {
Integer key = iterator.next();
System.out.println(key+"--"+stringMap.get(key));
}
}
运行结果:
注:
Set、List接口中有迭代器,map接口中没有迭代器,那么该怎么遍历?
-
Set< K >keySet():获取到所有的键,存储到一个Set集合中,并返回该集合,因为Set有迭代器,每次迭代出来的是一个键,再根据键来得到值
-
Set<Map.Entry<K,V>>entrySet():获取到所有的键值对形成的映射关系,存到一个Set集合中,再迭代这个集合每次迭代出来的是一个映射关系,从这个映射关系中既可以得到键,也可以得到值这种映射关系是Map.Entry<K,V>类型的。
- Entry是定义在Map中的一个静态成员,是一个接口
- Entry为什么定义在Map里面?
有了集合,有了集合中的键值对,才会存在映射关系,所以映射关系是对集合内部的事物描述所以定义在Map的内部
补充一些遍历容器的旧知识:
List<String> list = new ArrayList<>();
list.add("qqq");
list.add("aaa");
System.out.println(list);
for (String temp : list) {
System.out.println(temp);
}
Set<String> set = new HashSet<>();
set.add("ddd");
set.add("nnn");
System.out.println(set);
for (String temp : set) {
System.out.println(temp);
}
运行结果:
工具类Collections
注意:这里的工具类Collections和Collection接口是完全不同的东西!
package mycollections;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* 测试Collections常用工具类的使用
*
* @author 发达的范
* @date 2020/11/20 21:31
*/
public class TestCollections {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
for (int i = 0; i < 7; i++) {
list.add("HUFL" + i);
}
System.out.println(list);
Collections.shuffle(list);//随机打乱这个容器里对象的顺序
System.out.println(list);
Collections.reverse(list);//全部反转容器里的对象
System.out.println(list);
Collections.sort(list);//升序排列
System.out.println(list);
System.out.println(Collections.binarySearch(list,"HUFL6"));//二分查找法查找指定对象
Collections.fill(list, "IEEE");//用指定对象填充指定容器
System.out.println(list);
}
}
运行结果:
使用Map+List存储表格数据
表格如下:
ID | Name | Wages | Register date |
---|---|---|---|
唐三藏 | 1 | 10000 | 1234 |
孙悟空 | 2 | 20000 | 1235 |
猪八戒 | 3 | 30000 | 1236 |
思路:使用一个Map对象存储一行数据,然后使用List存储这些Map对象
package mycollection;
import java.util.*;
/**使用容器存储表格数据
*
* @author 发达的范
* @date 2020/11/20 22:12
*/
public class TestStoreData {
public static void main(String[] args) {
Map<String, Object> row1 = new HashMap<>();
row1.put("ID", 001);
row1.put("Name", "唐三藏");
row1.put("Wages", 10000);
row1.put("Register date", 1234);
Map<String, Object> row2 = new HashMap<>();
row2.put("ID", 002);
row2.put("Name", "孙悟空");
row2.put("Wages", 20000);
row2.put("Register date", 1235);
Map<String, Object> row3 = new HashMap<>();
row3.put("ID", 003);
row3.put("Name", "猪八戒");
row3.put("Wages", 30000);
row3.put("Register date", 1236);
List<Map<String, Object>> list = new ArrayList<>();
list.add(row1);
list.add(row2);
list.add(row3);
Iterator<Map<String, Object>> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
for (Iterator<Map<String, Object>> iterator1 = list.iterator(); iterator1.hasNext(); ) {
Map<String, Object> temp = iterator1.next();
// System.out.println(temp);//使用这句输出结果和上一种遍历方式的输出相同
System.out.print("Name:"+temp.get("Name")+" ");
System.out.print("ID:"+temp.get("ID")+" ");
System.out.print("Wages:"+temp.get("Wages")+" ");
System.out.println("Register date:"+temp.get("Register date")+" ");
}
}
}
运行结果:
两种遍历容器的方法本质上是相同的,只是第二种方式我是按照我指定的顺序显示数据。
当然,还可以使用其他容器结合来存储这个表格。