容器介绍
数组的优势:是一种简单的线性序列,可以快速地访问数组元素,效率高。如果从查询效率和类型检查的角度讲,数组是最好的。
数组的劣势:不灵活。容量需要事先定义好,不能随着需求的变化而扩容。比如:我们在一个用户管理系统中,要把今天注册的所有用户取出来,那么这样的用户有多少个?我们在写程序是无法确定,所以我们需要一种更强大、更灵活、容量随时可扩的容器来装载我们的对象,这就是容器,也叫集合(Collection)。
单例接口
双例接口
Collection表示一组对象,它是集中、收集的意思。Collection接口的两个子接口是List、Set接口。
Collection接口中定义的方法
方法 | 说明 |
boolean add(Object element) | 增加元素到容器中(增加成功返回true,增加失败返回false) |
boolean remove(Object element) | 从容器中移除元素(移除的元素存在返回true,不存在返回false) |
boolean contains(Object element) | 容器中是否包含该元素 |
int size() | 容器中元素的数量 |
boolean isEmpty() | 容器是否为空 |
void clear() | 清空容器中的所有元素 |
Iterator iterator | 获得迭代器,用于遍历所有元素 |
boolean containsAll(Collection C) | 本容器是否包含C容器中的所有元素 |
boolean addAll(Collection C) | 将容器C中的所有元素增加到本容器中 |
boolean removeAll(Collection C) | 移除本容器和容器C中都包含的元素 |
boolean retainAll(Collection C) | 取本容器和容器C中都包含的元素,移除非交集元素 |
Object[] toArray() | 转换成Object数组 |
由于List、Set是Collection子接口,意味着所有的List、Set的实现类都有上面的方法。
使用ArrayList来实现以上方法:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
public class ArrayListTest {
public static void main(String[] args) {
//实例化ArraysList容器
List<String> list = new ArrayList<>();
//添加元素
boolean flag1 = list.add("liming");
boolean flag2 = list.add("lihua");
boolean flag3 = list.add("wanger");
boolean flag4 = list.add("zhangsan");
System.out.println(flag1+"\t"+flag2+"\t"+flag3+"\t"+flag4);
//删除元素
boolean liming = list.remove("liming");
System.out.println(liming);
//获取元素个数
int size = list.size();
System.out.println(size);
//判断容器是否为空
boolean empty = list.isEmpty();
System.out.println(empty);
//判断容器是否包含指定元素
boolean wanger = list.contains("wanger");
System.out.println(wanger);
//清空容器
list.clear();
//将ArrarysList转换为数组
Object[] objects =list.toArray();
System.out.println(Arrays.toString(objects));
}
}
运行结果如下:
true true true true
true
3
false
true
[]
List接口介绍
List接口是有序、可重复的容器。
有序:有序(元素存入集合的顺序和取出的顺序一致)。List中每个元素都有索引标记。可以根据元素的索引标记(在List中的位置)访问元素,从而精确控制这些元素。
可重复:List允许加入重复的元素。更确切地将,List通常允许满主e1.equals(e2)的元素加入容器。
List接口中的常用方法
除了Collection接口中的方法,List多了一些跟顺序(索引)有关的方法:
方法 | 说明 |
void add(int index,Object element) | 在指定位置插入元素,以前元素全部后移一位 |
Object set(int index,Object element) | 修改指定位置的元素(返回被替换的元素) |
Object get(int index) | 返回指定位置的元素 |
Object remove(int index) | 删除指定位置的元素,后面元素全部前移一位(返回被删除的元素) |
int indexOf(Object o) | 返回第一个匹配元素的索引,如果没有该元素,返回-1 |
int lastIndexOf(Object o) | 返回最后一个匹配元素的索引,如果没有该元素,返回-1 |
ArrayList容器的基本使用
ArrayList是List接口的实现类。是List存储特征的具体实现。ArrayList底层是用数组实现的存储。特点:查询效率高,增删效率低,线程不安全。
ArrayList容器的索引操作
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ArrayListTest2 {
public static void main(String[] args) {
//实例化ArrayList容器
List<String> list = new ArrayList<>();
//添加元素
list.add("liming");
list.add("liming");
list.add("wanger");
//向指定位置添加元素
list.add(1,"lisi");
Object[] objects = list.toArray();
System.out.println(Arrays.toString(objects));
System.out.println("获取元素");
String s = list.get(1);
System.out.println(s);
System.out.println("获取所以元素方式一");
//使用普通循环
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
}
System.out.println("获取所以元素方式二");
for(String str:list){
System.out.println(str);
}
System.out.println("元素替换");
String k = list.set(1,"kevin");
System.out.println(k);
System.out.println("根据索引位置删除元素");
String remove = list.remove(1);
System.out.println(remove);
System.out.println("查找元素在容器中第一次出现的位置");
int ss = list.indexOf("lisi");
System.out.println(ss);
System.out.println("查找元素在容器中最后一次出现的位置");
list.add("lisi");
int ss1 = list.lastIndexOf("lisi");
System.out.println(ss1);
}
}
执行结果如下:
[liming, lisi, liming, wanger]
获取元素
lisi
获取所以元素方式一
liming
lisi
liming
wanger
获取所以元素方式二
liming
lisi
liming
wanger
元素替换
lisi
根据索引位置删除元素
kevin
查找元素在容器中第一次出现的位置
-1
查找元素在容器中最后一次出现的位置
3
ArrayList的并集、交集、差集
import java.util.ArrayList;
import java.util.List;
public class ArrayTest3 {
public static void main(String[] args) {
//并集操作:将另一个容器中的元素添加到当前容器中
List<String> a = new ArrayList<>();
a.add("a");
a.add("b");
a.add("c");
List<String> b = new ArrayList<>();
b.add("a");
b.add("b");
b.add("c");
//a并集b
a.addAll(b);
for(String str :a){
System.out.println(str);
}
System.out.println("------------------");
//交集操作:保留相同的,删除不同的
List<String> a1 = new ArrayList<>();
a1.add("a");
a1.add("b");
a1.add("c");
List<String> b1 = new ArrayList<>();
b1.add("a");
b1.add("d");
b1.add("e");
//交集操作
a1.retainAll(b1);
for(String str :a1){
System.out.println(str);
}
System.out.println("-------------");
//差集操作:保留不同的,删除相同的
List<String> a2 = new ArrayList<>();
a2.add("a");
a2.add("b");
a2.add("c");
List<String> b2= new ArrayList<>();
b2.add("b");
b2.add("c");
b2.add("d");
a2.removeAll(b2);
for(String str :a2){
System.out.println(str);
}
}
}
运行结果:
a
b
c
a
b
c
------------------
a
-------------
a
Vector容器
Vector底层是用数组实现的,相关方法都加了同步检查,因此“线程安全,效率低”。比如:indexOf方法就增加了synchronized同步标记。
public synchronized int indexOf(Object o,int index){
//代码省略
}
synchronized让并行(多线程)变为串行(单线程)来提高安全性。
Vector的使用
Vector的使用与ArrayList是相同的,因为他们都实现了List接口,对List接口中的抽象方法做了具体实现。
import java.util.List;
import java.util.Vector;
public class VectorTest {
public static void main(String[] args) {
//实例化Vector容器
List<String> v = new Vector<>();
//添加
v.add("a");
v.add("b");
v.add("c");
v.add("a");
//遍历Vector容器或者使用for-each方法
for(int i=0;i<v.size();i++){
System.out.println(v.get(i));
}
}
}
LinkedList容器介绍
LinkedList底层用双向链表实现的存储。特点:查询效率低,增删效率高,线程不安全。
双向链表也叫双链表,是链表的一种,它的每个数据节点中都有两个指针,分别指向前一个节点和后一个节点,所以,从双向列表中的任意一个节点开始,都可以很方便地找到所有节点。
LinkedList容器的使用
LinkedList实现了List接口,所以LinkedList是具备List的存储特征的(有序,可重复)。
import java.util.LinkedList;
import java.util.List;
public class LinkedListTest {
public static void main(String[] args) {
//实例化LinkedList容器
List<String> list = new LinkedList<>();
//添加元素
boolean a = list.add("a");
boolean b = list.add("b");
boolean c = list.add("c");
list.add(3,"a");
System.out.println(a+"\t"+b+"\t"+c);
//获取容器中的所有元素
for(int i=0;i<list.size();i++){
System.out.println(list.get(i));
//这个方法中的i不再指数组下标,而指节点的第i个位置,因为这是链表不是数组
}
}
}
LinkedList容器的使用标准(非List标准)
是LinkedList独有的方法,只能在LinkedList中用,实例化LinkedList容器时与上方有差异,例如:LinkedList<String> list = new LinkedList<>();而不是List<String> list = new LinkedList<>();
方法 | 说明 |
void addFirst(E e) | 将指定元素插入到开头 |
void addLast(E e) | 将指定元素插入到结尾 |
getFirst() | 返回此链表的第一个元素 |
getLast() | 返回此链表的最后一个元素 |
removeFirst() | 移除此链表中的第一个元素,并返回这个元素 |
removeLast() | 移除此链表中的最后一个元素,并返回这个元素 |
E pop() | 从此链表所表示的堆栈处弹出一个元素,等效于removeFirst |
void push(E e) | 将此元素推入此链表所表示的堆栈,这个等效于addFirst(E e) |
import java.util.LinkedList;
public class LinkedlistTest {
public static void main(String[] args) {
//示例化LinkedList容器
LinkedList<String> list = new LinkedList<>();
//将指定元素插入到开头
list.addFirst("a");
list.addFirst("b");
list.addFirst("c");
for(String str:list){
System.out.println(str);
}
System.out.println("--------------------");
//将指定元素插入到结尾
LinkedList<String> list2 = new LinkedList<>();
list2.addLast("a");
list2.addLast("b");
list2.addLast("c");
for(String str:list2){
System.out.println(str);
}
System.out.println("--------------------");
//返回此链表的第一个元素
System.out.println(list2.getFirst());
//返回此链表的最后一个元素
System.out.println(list2.getLast());
System.out.println("--------------------");
//移除此链表中的第一个元素,并返回这个元素
/*String s = list2.removeFirst();
System.out.println(s+" S");*/
//从此链表所表示的堆栈处弹出一个元素,等效于removeFirst
System.out.println(list2.pop()+" S");
//移除此链表中的最后一个元素,并返回这个元素
String s1 = list2.removeLast();
System.out.println(s1+" S1");
//将元素推入此链表所表示的堆栈 这个等效于addFisrt(E e)
list2.push("e");
for(String str:list2){
System.out.println(str);
}
}
}
执行如下:
c
b
a
--------------------
a
b
c
--------------------
a
c
--------------------
a S
c S1
e
b
Set接口
Set接口继承自Collection接口,Set接口中没有新增方法,它和Collection接口保持完全一致。前面学习的List接口的方法在Set中同样适用。
Set接口的特点:无序,不可重复。无序指Set中的元素没有索引,我们只能遍历查找,不可重复指不允许加入重复元素,更确切的将,新元素如果和Set中某个元素通过equals()方法对比为true,则只能保留一个。
Set常用的实现类有:HashSet、TreeSet等。我们一般使用HashSet。
HashSet容器的使用
HashSet是Set接口的实现类。是Set存储特征带的具体实现。
import java.util.HashSet;
import java.util.Set;
public class HashSetTest {
public static void main(String[] args) {
//实例化HashSet容器
Set<String> set = new HashSet<>();
//添加元素
boolean a = set.add("a");
boolean b = set.add("b1");
boolean c = set.add("c1");
boolean a1 = set.add("a");
System.out.println(a+"\t"+b+"\t"+c+"\t"+a1);
System.out.println("----------------");
boolean c1 = set.remove("c1");
System.out.println(c1);
//获取元素:在Set接口类型的容器中,并没有提供获取指定位置的元素的get(int index)方法。
for(String str:set){
System.out.println(str); //输出结果是无序的
}
System.out.println("-----------------");
//删除元素
boolean flag = set.remove("c1");
System.out.println(flag);
for(String str:set){
System.out.println(str);
}
System.out.println("-----------------");
int size = set.size();
System.out.println(size);
}
}
HashSet存储特征
HashSet是一个不保证元素的顺序且没有重复元素的集合,是线程不安全的,HashSet允许有null元素。
无序:在HashSet中底层是使用HashMap存储元素的,HashMap底层使用的是数组与链表实现元素的存储。元素在数组中存放时,并不是有序存放的也不是随机存放的,而对元素的哈希值进行运算决定元素在数组中的位置
不重复:当两个元素的哈希值进行运算后得到相同的在数组中的位置时,会调用元素的equals()方法判断两个元素是否相同。如果元素相同则不会添加该元素,如果不相同则会使用单向链表保存该元素。
通过HashSet存储自定义对象
创建Users对象
import java.util.Objects;
public class Users implements Comparable<Users>{ //这个泛型类型就是对哪个对象的比较规则的定义
private String username;
private int userage;
public Users(String username, int userage) {
this.username = username;
this.userage = userage;
}
public Users() {
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public int getUserage() {
return userage;
}
public void setUserage(int userage) {
this.userage = userage;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Users users = (Users) o;
return userage == users.userage && Objects.equals(username, users.username);
}
@Override
public int hashCode() {
return Objects.hash(username, userage);
}
@Override
public String toString() {
return "Users{" +
"username='" + username + '\'' +
", userage=" + userage +
'}';
}
//定义比较规则
//正数:大,负数:小 0:相等
@Override
public int compareTo(Users o) {
if(this.userage > o.getUserage()){
return 1;
}
if(this.userage == o.getUserage()){
return this.username.compareTo(o.getUsername());//调用String类型的compareTo来判断,因为姓名是字符串
}
return -1;
}
}
在HashSet中存储Users对象
import java.util.HashSet;
import java.util.Set;
public class HashSetTest2 {
public static void main(String[] args) {
//实例化HashSet容器
Set<Users> set = new HashSet<>(); //因为是存储对象,泛型中的类型应该是Users类型
//实例化Users
Users u1 = new Users("oldlu",18);
Users u2 = new Users("oldlu",18);
System.out.println(u1.hashCode());
//Set接口是无序,不重复的,如果上面Users类没有重写hashCode()方法,默认调用Object的hashCode()方法,u1和u2的hashCode值会不同,所以会set容器里面会有两个相同的元素u1 和u2
System.out.println(u2.hashCode());
System.out.println(u1.equals(u2));
//使用没有重写的equals()方法比较u1和u2,会返回false
//在HashSet类中使用Users之前需要先在Users类中重写hashCode()方法和equals()方法
//添加到容器中
set.add(u1);
set.add(u2);
//遍历容器
for(Users u:set){
System.out.println(u);
}
}
}
TreeSet
TreeSet实现了Set接口,它是一个可以对元素进行排序的容器,底层实际是用TreeMap实现的,内部维持了一个简化版的TreeMap,通过key来存储元素。TreeSet内部需要对存储元素进行排序,因此需要给定排序规则。
排序规则实现方式:
通过元素自身实现比较规则
通过比较器指定比较规则
1.在元素自身实现比较规则时,需要实现Comparable接口中的compareTo方法,该方法中用来定义比较规则。TreeSet通过调用该方法来完成对元素的的排序处理。(上面Users类已经完成compareTo方法的定义)。下面使用TreeSet来调用该方法进行排序处理。
注意:String类和常见的类型实现的包装类都实现了Comparable接口中的compareTo方法,因此不需要重新定义。
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
public class TreeSetTest {
public static void main(String[] args) {
//实例化TreeSet容器
Set<Users> set = new TreeSet<>();
//实例化Users
Users u1 = new Users("lu",18);
Users u2 = new Users("sx",22);
Users u3 = new Users("admin",22);
//添加到容器中
set.add(u1);
set.add(u2);
set.add(u3);
for(Users u:set){
System.out.println(u);
}
}
}
2.通过外部比较器实现比较规则时,我们需要单独创建一个比较器,比较器需要实现Comparator接口中的compare方法来定义比较规则。在实例化TreeSet时将比较器对象交给TreeSet来完成元素的排序处理,此时元素自身就不需要实现比较规则了。
创建一个Student类
import java.util.Objects;
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age && Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
创建比较器
import java.util.Comparator;
/**
* 定义比较器
*/
public class StudentComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
if(o1.getAge() > o2.getAge()){
return 1;
}
if(o1.getAge() == o2.getAge()){
return o1.getName().compareTo(o2.getName());
}
return -1;
}
}
import java.util.Set;
import java.util.TreeSet;
public class TreeSetTest3 {
public static void main(String[] args) {
//创建TreeSet容器时需要给定比较器对象
Set<Student> set = new TreeSet<>(new StudentComparator());
//创建Student对象
Student s = new Student("oldu",18);
Student s1 = new Student("sxt",22);
Student s2 = new Student("admin",22);
//添加元素
set.add(s);
set.add(s1);
set.add(s2);
for(Student student: set){
System.out.println(student);
}
}
}
双例集合
Map接口
Map接口定义了双例集合的存储特征,它并不是Collection接口的子接口。双例集合的存储特征是以key与value结构为单位进行存储。体现的是数学中的函数y=f(x)感念。
Map与Collection的区别:
1.Collection中的容器,元素是孤立存在的(理解为单身),向集合中存储元素采用一个个元素的方式存储。
2.Map中的容器,元素是成对存在的(理解为现代社会的夫妻)。每个元素由键与值两部分组成,通过键可以找对所对应的值。
3.Collection中的容器称为单列集合,Map中的容器称为双列集合。
4.Map中的集合不能包含重复的键,值可以重复;每个键只能对应一个值。
6.Map中常用的容器为HashMap,TreeMap等。
Map接口中常用的方法表
方法 | 说明 |
V put(K key,V value) | 把key与value添加到Map集合中 |
void putAll(Map m) | 从指定Map中将所有映射关系赋值到此Map中(并集操纵)若a的key和b的相同,那么a的value就会被b的value替换 |
V remove(Object key) | 删除key对应的value |
V get(Object key) | 根据指定的key,获得对应的value |
boolean containsKey(Object key) | 判断容器中是否包含指定的key |
boolean containsValue(Object value) | 判断容器中是否包含指定的value |
Set keySet() | 获取Map集合中所有的key,存储到Set集合 |
Set<Map.Entry<K,V>>entrySet() | 返回一个Set基于Map.Entry类型包含Map中的所有映射 |
void clear() | 删除Map中所有的映射 |
HashMap容器的使用
HashMap采用哈希算法实现,是Map接口最常用的实现类。由于底层采用了哈希表存储数据,我们要求键不能重复,如果发生重复,新的键值对会替换旧的键值对。HashMap在查找、删除、修改方面都有非常高的效率。
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class HashMapTest {
public static void main(String[] args) {
//实例化HashMap容器
Map<String,String> map = new HashMap<>();
//添加元素
String put1 = map.put("a", "A");
String put2 = map.put("b", "B");
String put3 = map.put("c", "C");
String put4 = map.put("a", "AA");
System.out.println(put1+"\t"+put2+"\t"+put3+"\t"+put4);
System.out.println("---------------");
//获取容器中元素的数量
int size = map.size();
System.out.println(size);
System.out.println("-----------------");
//获取容器中的元素
//方式一
String v = map.get("a");
System.out.println(v);
System.out.println("-------------");
//方式二
Set<String> keySet = map.keySet();
for(String key : keySet){
String value = map.get(key);
System.out.println(key +" ------ "+ value);
}
System.out.println("--------------------");
//方式三
//Map.Entry就是一个键值对对象
Set<Map.Entry<String, String>> entrySet = map.entrySet();
//遍历Set获取每一个键值对
for(Map.Entry<String,String> entry:entrySet){
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key+"-------------"+value);
}
System.out.println("------------------------");
//Map容器的并集操作
Map<String,String> map2 = new HashMap<>();
map2.put("f","F");
map2.put("c","CC");
map.putAll(map2);
Set<String> keySet2 = map.keySet();
for(String key : keySet2){
String value = map.get(key);
System.out.println(key +" ------ "+ value);
}
System.out.println("--------------------");
//删除元素
String a = map.remove("a");
System.out.println(a);
System.out.println("--------------");
//判断Key是否存在
boolean b = map.containsKey("b");
System.out.println(b);
System.out.println("-----------------");
//判断Value是否存在
boolean b1 = map.containsValue("B");
System.out.println(b1);
}
}
HashTable类和HashMap用法几乎一样,底层实现几乎一样,只不过HashTable的方法添加了synchronized关键字确保线程同步检查,效率较低。
HashMap与HashTable的区别:
1.HashMap:线程不安全,效率高。允许key或value为null
2.HashTable:线程安全,效率低。不允许key或value为null
TreeMap
TreeMap和HashMap同样实现了Map接口,所以,对于API的用法来说是没有区别的。HashMap效率高于TreeMap;TreeMap是可以对键进行排序的一种容器,在需要对键排序时可选用TreeMap。TreeMap底层是基于红黑树实现的。
在使用TreeMap时需要给定排序规则:
1.元素自身实现比较规则
2.通过比较器实现比较规则
元素自身实现比较规则
创建一个Users类,如上
创建一个TreeMapTest类
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class TreeMapTest {
public static void main(String[] args) {
//实例化TreeMap容器
Map<Users,String> map = new TreeMap<>();
//实例化Users
Users u = new Users("oldlu",18);
Users u2 = new Users("sxt",22);
Users u3 = new Users("admin",22);
//添加元素
map.put(u,u.getUsername());
map.put(u2,u2.getUsername());
map.put(u3,u3.getUsername());
//获取TreeMap容器中key
Set<Users> keySet = map.keySet();
for(Users key:keySet){
System.out.println(key+" ---- "+map.get(key));
}
}
}
通过比较器实现比较规则
创建一个student类和比较器StudentComparator如上
再创建一个TreeMapTest2
import com.itbaizhan.set.Student;
import com.itbaizhan.set.StudentComparator;
import com.itbaizhan.set.Users;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class TreeMapTest2 {
public static void main(String[] args) {
//实例化TreeMap容器
Map<Student,String> map = new TreeMap<>(new StudentComparator());
//Student对象
Student s = new Student("oldlu",18);
Student s1 = new Student("sxt",22);
Student s2 = new Student("admin",22);
map.put(s,s.getName());
map.put(s1,s1.getName());
map.put(s2,s2.getName());
Set<Student> keySet = map.keySet();
for(Student key:keySet){
System.out.println(key+" ------ "+map.get(key));
}
}
}
Iterator接口
lterator迭代器接口介绍
Collection接口继承了lterable接口,在该接口中包含一个名为iterator的抽象方法,所有实现了Collection接口的容器类对该方法做了具体实现。iterator方法会返口一个iterator接口类型的迭代器对象,在该对象中包含了三个方法用于实现对单例容器的迭代处理。
Iterator迭代器的使用
迭代List接口类型的容器
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class IteratorListTest {
public static void main(String[] args) {
//实例化ArrayList容器
List<String> list = new ArrayList<>();
//添加元素
list.add("a");
list.add("b");
list.add("c");
list.add("d");
//方式一: 在迭代器中,通过while循环获取元素
//获取迭代器
Iterator<String> it = list.iterator();
while(it.hasNext()){
String value = it.next();
System.out.println(value);
}
System.out.println("------------------------");
//方式二:在迭代器中,通过for循环获取元素
for(Iterator<String> it2 = list.iterator();it2.hasNext();){
String next = it2.next();
//it2.next(); 如果反复调用会因为找不到元素而报错,一次循环里面只能调用一次next()方法
System.out.println(next);
}
}
}
迭代Set接口的容器
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class IteratorSetTest {
public static void main(String[] args) {
//实例化HashSet容器
Set<String> set = new HashSet<>();
set.add("a");
set.add("b");
set.add("c");
set.add("d");
//方式一:在迭代器中,通过while循环获取元素
//获取迭代器对象
Iterator<String> iterator = set.iterator();
while(iterator.hasNext()){
String next = iterator.next();
System.out.println(next);
}
System.out.println("---------------------");
//方式二:在迭代器中,通过for循环获取元素
for(Iterator<String> iterator1 = set.iterator();iterator1.hasNext();){
String next = iterator1.next();
System.out.println(next);
}
}
}
迭代Map接口类型容器
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class IteratorMapTest {
public static void main(String[] args) {
//实例化HashMap容器
Map<String,String> map = new HashMap<>();
//添加元素
map.put("a","A");
map.put("b","B");
map.put("c","C");
map.put("d","D");
//方式一:通过keySet方法获取所有的key
Set<String> keySet = map.keySet();
//获取迭代器
Iterator<String> iterator = keySet.iterator();
while(iterator.hasNext()){
String key = iterator.next();
System.out.println(key+" ------------ "+map.get(key));
}
System.out.println("------------------");
//方式二:通过Map.entry方法获取所有的Map.Entry对象
Set<Map.Entry<String, String>> entrySet = map.entrySet();
for(Iterator<Map.Entry<String, String>> iterator1 = entrySet.iterator();iterator1.hasNext();){
Map.Entry<String, String> entry = iterator1.next();
System.out.println(entry.getKey()+" ------ "+entry.getValue());
}
}
}
在迭代器中删除元素
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
public class IteratorRemoveTest {
public static void main(String[] args) {
//实例化ArrayList容器
List<String> list = new ArrayList<>();
for(Iterator<String> it = list.iterator();it.hasNext();){
System.out.println(it.next());
list.add("dddd");
}
//添加元素
list.add("a");
list.add("b");
list.add("c");
list.add("d");
/*for(int i=0;i<list.size();i++){
list.remove(i);
}*/
/*for(String str:list){
list.remove(str);
System.out.println(str);
}*/
for(Iterator<String> it = list.iterator();it.hasNext();){
it.next();
it.remove(); //next()必须在remove()前,否则会报错
}
for(String str:list){
System.out.println(str);
}
}
}
在删除元素或者添加元素过程中都不要在迭代的过程(普通for循环或者for-each循环或者Iterator)中进行,如果真需要迭代删除的话,只能使用Iterator来删除。
遍历集合方法总结
Collections工具类
Collections是操作容器的工具类,类java.util.Collections提供了对Set、List、Map进行排序、填充、查找元素的辅助方法。
方法名 | 说明 |
void sort(List) | 对List容器内的元素排序,排序规则是升序。 |
void shuffle(List) | 对List容器内的元素进行随机排序 |
void reverse(List) | 对List容器内的元素进行逆序排序 |
void fill(List,Object) | 用一个特定的对象重写整个List容器 |
int binarySearch(List,Object) | 对于顺序的List容器,折半查找查找特定对象 |
Collections工具类的常用方法
import com.itbaizhan.set.Student;
import com.itbaizhan.set.StudentComparator;
import com.itbaizhan.set.Users;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class CollectionsTest {
public static void main(String[] args) {
//实例化ArrayList容器
List<String> list = new ArrayList<>();
list.add("c");
list.add("b");
list.add("a");
//对元素排序
Collections.sort(list);
//字符串String自身实现了比较器,可以直接使用sort方法进行排序
for(String str:list){
System.out.println(str);
}
System.out.println("----------------");
List<Users> list2 = new ArrayList<>();
Users u = new Users("oldlu",18);
Users u2 = new Users("sxt",22);
Users u3 = new Users("admin",22);
list2.add(u);
list2.add(u2);
list2.add(u3);
Collections.sort(list2);
for(Users users:list2){
System.out.println(users);
}
System.out.println("-----------------------");
List<Student> list3 = new ArrayList<>();
Student s = new Student("oldlu",18);
Student s2 = new Student("sxt",20);
Student s3 = new Student("admin",20);
list3.add(s);
list3.add(s2);
list3.add(s3);
Collections.sort(list3,new StudentComparator());
for(Student student:list3){
System.out.println(student);
}
System.out.println("------------------------");
List<String> list4 = new ArrayList<>();
list4.add("a");
list4.add("b");
list4.add("c");
list4.add("d");
//洗牌
Collections.shuffle(list4);
for(String str: list4){
System.out.println(str);
}
}
}