集合
集合类
- 集合是一个容器,是用来存储和获取数据的。
- 特点:长度可变
集合类体系结构
- 集合体系图
Collection集合
概述
- Collection:是单列集合的顶层接口。
- Collection:表示一组对象,这些对象也称为 collection 的元素。
一些 collection 允许有重复的元素,而另一些则不允许。
一些 collection 是有序的,而另一些则是无序的。 - JDK 不提供此接口的任何直接实现:它提供更具体的子接口(如 Set 和 List)实现。
创建Collection对象
- 创建Collection集合的对象,采用的是多态的方式
- 使用的是具体的ArrayList类:
-
ArrayList() // 因为这个类是最常用的集合类
-
Collection< E >: < E >:是一种特殊的数据类型,泛型。 在出现E的地方用引用数据类型替换即可。
成员方法
-
boolean add(E e):添加元素 // 永远返回true boolean remove(Object o):从集合中移除元素 void clear():清空集合中的元素 boolean contains(Object o):判断集合中是否存在指定的元素 boolean isEmpty():判断集合是否为空 int size():集合的长度,也就是集合中元素的个数
示例1:
public class CollectionDemo {
public static void main(String[] args) {
//创建Collection集合对象
Collection<String> c = new ArrayList<String>(); //多态的方式
//boolean add(E e):添加元素
c.add("hello");
c.add("world");
c.add("java");
//输出集合对象
System.out.println(c);
//输出了集合中的元素按照指定格式拼接的内容,说明ArrayList重写了toString()方法
}
}
示例2:
import java.util.ArrayList;
import java.util.Collection;
public class CollectionDemo2 {
public static void main(String[] args) {
//创建集合对象
Collection<String> c = new ArrayList<String>();
//通过查看源码,我们知道ArrayList集合的add方法的返回值永远都是true
c.add("hello");
c.add("world");
c.add("java");
//boolean remove(Object o):从集合中移除元素
//System.out.println("remove:"+c.remove("world"));
System.out.println("remove:"+c.remove("haha")); //返回false
//void clear():清空集合中的元素
//c.clear();
//boolean contains(Object o):判断集合中是否存在指定的元素
System.out.println("contains:"+c.contains("world"));
System.out.println("contains:"+c.contains("haha"));
//boolean isEmpty():判断集合是否为空
System.out.println("isEmpty:"+c.isEmpty());
//int size():集合的长度,也就是集合中元素的个数
System.out.println("size:"+c.size());
//输出集合对象
System.out.println(c);
}
}
Collection集合遍历
迭代器Iterator
-
概述:返回在此 collection 的元素上进行迭代的迭代器:
-
Iterator< E > iterator(): // 通过集合对象调用iterator()方法可得到(返回)迭代器对象。 // 返回的是接口的对应实现类对象。
-
Iterator方法:
-
E next():返回迭代的下一个元素。 boolean hasNext():如果仍有元素可以迭代,则返回 true。
示例
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionDemo3 {
public static void main(String[] args) {
//创建集合对象
Collection<String> c = new ArrayList<String>();
//添加元素
c.add("hello");
c.add("world");
c.add("java");
//Iterator<E> iterator()
Iterator<String> it = c.iterator();//返回的是迭代器接口的实现类的对象
//boolean hasNext()
while(it.hasNext()){
//System.out.println(it.next());
String s = it.next();
System.out.println(s);
}
}
}
案例
-
需求:Collection集合存储自定义对象并遍历。自定义一个学生类,给出成员变量name和age;遍历集合的时候,在控制台输出学生对象的成员变量值。
-
集合的使用步骤
- 创建集合对象
- 创建元素对象
- 把元素添加到集合
- 遍历集合
- 代码:展示学生类的测试部分
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionTest {
public static void main(String[] args) {
//创建集合对象
Collection<Student> c = new ArrayList<Student>();
//创建元素对象
Student s1 = new Student("林青霞",30);
Student s2 = new Student("张曼玉",35);
Student s3 = new Student("王祖贤",33);
//把元素添加到集合
c.add(s1);
c.add(s2);
c.add(s3);
//遍历集合
Iterator<Student> it = c.iterator();
while(it.hasNext()){
Student s = it.next();
System.out.println(s.getName()+"---"+s.getAge());
}
}
}
List集合
概述
- List:有序的 collection(也称为序列)
- 有序:此接口的用户可以对列表中每个元素的插入位置进行精确地控制
- 用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素、
- 与 set 不同,列表通常允许重复的元素
特点
- 有序(存储和取出元素的顺序一致)
- 存储的元素可以重复
使用示例
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ListDemo {
public static void main(String[] args) {
//创建集合对象
List<String> list = new ArrayList<String>();
//存储元素
list.add("hello");
list.add("world");
list.add("java");
list.add("world"); // 元素可重复
//遍历集合
Iterator<String> it = list.iterator();
while(it.hasNext()){
String s = it.next();
System.out.println(s);
}
}
}
特有成员方法
根据List的指定位置的特性(有序):
-
void add(int index,E element):在指定位置添加元素 E remove(int index):删除指定位置的元素,并返回被删除的元素 E get(int index):获取指定位置的元素 E set(int index,E element):修改指定位置的元素,并返回被修改的元素
-
示例
import java.util.ArrayList;
import java.util.List;
public class ListDemo2 {
public static void main(String[] args) {
//创建集合对象
List<String> list = new ArrayList<String>();
//使用继承Collection的添加功能
list.add("hello");
list.add("world");
list.add("java");
//void add(int index,E element):在指定位置添加元素
list.add(1, "javaee");
//下面语句的情况会产生:IndexOutOfBoundsException
//list.add(11,"javase");
//E remove(int index):删除指定位置的元素,返回被删除的元素
System.out.println("remove:"+list.remove(1));
//System.out.println("remove:"+list.remove(11));
//E get(int index):获取指定位置的元素
System.out.println("get:"+list.get(1));
//E set(int index,E element):修改指定位置的元素,返回被修改的元素
System.out.println("set:"+list.set(1, "java"));
//输出集合对象
System.out.println(list);
}
}
列表迭代器ListIterator
概述
ListIterator:
ListIterator listIterator():返回此列表元素的列表迭代器
public interface ListIteratorextends Iterator
特有功能:
E previous():返回列表中的前一个元素。
boolean hasPrevious():如果以逆向遍历列表,列表迭代器有多个元素,则返回 true。
注意:ListIterator可以实现逆向遍历,但是要求先正向遍历,才能逆向遍历。
使用示例
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class ListIteratorDemo {
public static void main(String[] args) {
//创建集合对象
List<String> list = new ArrayList<String>();
//添加元素
list.add("hello");
list.add("world");
list.add("java");
ListIterator<String> lit = list.listIterator();
// 正向遍历
// while(lit.hasNext()){
// String s = lit.next();
// System.out.println(s);
// }
System.out.println("--------------------------");
//逆向遍历
while(lit.hasPrevious()) {
String s = lit.previous();
System.out.println(s);
}
}
}
增强for循环
-
增强for循环:是for循环的一种,其实是用来替代迭代器的
-
格式:
-
for(元素的数据类型 变量名 : 数组名或者Collection集合对象名) { 使用变量名即可,这个变量名代表的其实就是数组或者Collection集合中的元素 }
-
好处:简化了数组和Collection集合的遍历
-
弊端:目标不能为null(需要在遍历前先对目标进行不为null的判断)
-
使用示例
import java.util.ArrayList;
import java.util.List;
public class ForDemo {
public static void main(String[] args) {
//定义一个int类型的数组
int[] arr = {1,2,3,4,5};
//普通for
for(int x=0; x<arr.length; x++) {
System.out.println(arr[x]);
}
System.out.println("---------");
//增强for
for(int x : arr) {
System.out.println(x);
}
System.out.println("---------");
//定义一个String类型的数组
String[] strArray = {"hello","world","java"};
//增强for
for(String s : strArray) {
System.out.println(s);
}
System.out.println("---------");
//创建集合对象
List<String> list = new ArrayList<String>();
list.add("hello");
list.add("world");
list.add("java");
//增强for
for(String s :list) {
System.out.println(s);
}
}
}
List集合遍历
-
List集合的遍历方式:
-
A:迭代器 B:普通for循环 C:增强for循环
-
需求:
ArrayList集合存储自定义对象并遍历
自定义一个学生类,给出成员变量name和age
遍历集合的时候,在控制台输出学生对象的成员变量值 -
代码
创建一个Student类:
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = 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;
}
}
Student类测试:
import java.util.ArrayList;
import java.util.Iterator;
public class ArrayListTest {
public static void main(String[] args) {
//创建集合对象
ArrayList<Student> array = new ArrayList<Student>();
//创建元素对象
Student s1 = new Student("林青霞",30);
Student s2 = new Student("张曼玉",35);
Student s3 = new Student("王祖贤",33);
//把元素添加到集合
array.add(s1);
array.add(s2);
array.add(s3);
//方式一:迭代器
Iterator<Student> it = array.iterator();
while(it.hasNext()){
Student s = it.next();
System.out.println(s.getName()+"---"+s.getAge());
}
System.out.println("----------------------");
//方式二:普通for
for(int x=0; x<array.size(); x++) {
Student s = array.get(x);
System.out.println(s.getName()+"---"+s.getAge());
}
System.out.println("----------------------");
//方式三:增强for
for(Student s : array) {
System.out.println(s.getName()+"---"+s.getAge());
}
}
}
并发修改异常
概述
ConcurrentModificationException:
当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。
案例分析
我有一个集合:List list = new ArrayList();
里面有三个元素list.add(“hello”);list.add(“world”);list.add(“java”);
我想判断里面有没有"world"这个元素,如果有,我就添加一个"javaee"元素,请写代码实现。
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class ListIteratorDemo {
public static void main(String[] args) {
// 创建集合对象
List<String> list = new ArrayList<String>();
// 添加元素
list.add("hello");
list.add("world");
list.add("java");
//我想判断里面有没有"world"这个元素,如果有,我就添加一个"javaee"元素
Iterator<String> it = list.iterator();
while(it.hasNext()){
String s = it.next();
if(s.equals("world")) {
list.add("javaee");
}
}
产生的原因:
迭代器依赖于集合而存在,在判断成功后,集合中添加了新的元素,而迭代器并不知道,因此就报错了。
解决方法:
- 迭代器遍历的时候,可以通过迭代器修改集合中的元素:
-
//此时修改的元素是跟在刚才迭代(指向)的元素后面的
- 集合遍历的时候,可以通过集合对象修改集合中的元素
-
//此时修改的元素是在集合最后添加的
代码:
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class ListIteratorDemo {
public static void main(String[] args) {
// 创建集合对象
List<String> list = new ArrayList<String>();
// 添加元素
list.add("hello");
list.add("world");
list.add("java");
//迭代器遍历的时候,通过迭代器修改集合中的元素
ListIterator<String> lit = list.listIterator();
while(lit.hasNext()) {
String s = lit.next();
if(s.equals("world")) {
lit.add("javaee");
}
}
//集合遍历的时候,通过集合对象修改集合中的元素
// for(int x=0; x<list.size(); x++) {
// String s = list.get(x);
// if(s.equals("world")) {
// list.add("javaee");
// }
// }
System.out.println(list);
}
}
Set集合
- Set集合的特点: 元素唯一;存储元素无序
是一个不包含重复元素的 collection
HashSet
- 特点:它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变
保证元素唯一性的原理
-
在add方法中:添加功能的执行过程中,是进行了数据的判断的
-
判断的流程:
- 首先比较对象的哈希值是否相同,这个哈希值是根据对象的hashCode()计算出来的
- 如果哈希值不同,就直接添加到集合中
- 如果哈希值相同,继续执行equals()进行比较,
若返回的是true,说明元素重复,不添加。
若返回的是false,说明元素不重复,就添加。
- 注意:
若使用HashSet集合存储对象,为保证元素的唯一性,就必须重写对象所在类的hashCode()和equals()方法
案例
-
要求:HashSet集合存储自定义对象,保证元素唯一性并遍历
即如果对象的成员变量值相同,就认为是同一个元素 -
注意:
需要在所属的类中重写hashCode()和equals()方法 -
代码示例:
提示:自定义一个学生类,给出成员变量name和age。遍历集合的时候,在控制台输出学生对象的成员变量值。
两种方式遍历
迭代器
增强for
Student类
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = 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;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
HashSet测试类
import java.util.HashSet;
public class HashSetTest {
public static void main(String[] args) {
//创建集合对象
HashSet<Student> hs = new HashSet<Student>();
//创建元素对象
Student s1 = new Student("林青霞",30);
Student s2 = new Student("张曼玉",35);
Student s3 = new Student("王祖贤",33);
Student s4 = new Student("林青霞",30);
Student s5 = new Student("张曼玉",35);
//把元素添加到集合
hs.add(s1);
hs.add(s2);
hs.add(s3);
hs.add(s4);
hs.add(s5);
//遍历集合
//增强for
for(Student s : hs) {
System.out.println(s.getName()+"---"+s.getAge());
}
}
}
Map集合
概述
- 将键映射到值的对象
例如:学生的学号和姓名
001 林青霞
002 张曼玉
003 王祖贤 -
public interface Map<K,V> K -- key;V -- value;
注意
一个映射不能包含重复的键
每个键最多只能映射到一个值
键不可重复(唯一性)
示例
创建Map集合对象并添加元素
import java.util.HashMap;
import java.util.Map;
public class MapDemo {
public static void main(String[] args) {
//创建集合对象
Map<String,String> map = new HashMap<String,String>();
//添加元素
//put(K key,V value):添加元素。
map.put("it001", "林青霞");
map.put("it002", "张曼玉");
map.put("it003", "王祖贤");
//输出集合对象
System.out.println(map);
}
}
成员方法
-
常用方法:
-
V put(K key,V value):添加元素,并返回该键上一次所指(被替换)的元素 V remove(Object key):根据键删除键值对元素并返回被删元素 void clear():移除所有的键值对元素 boolean containsKey(Object key):判断集合是否包含指定的键 boolean containsValue(Object value):判断集合是否包含指定的值 boolean isEmpty():判断集合是否为空 int size():返回集合中的键值对的对数
-
获取方法:
-
V get(Object key):根据键获取值 Set<K> keySet():获取所有键的集合 Collection<V> values():获取所有值的集合 Set<Map.Entry<K,V>> entrySet():获取键值对对象的集合
遍历
方式一:键找值
- 思路:
- 获取所有键的集合
- 遍历键的集合,获取到每一个键
- 根据键去找值
- 示例
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MapDemo {
public static void main(String[] args) {
//创建集合对象
Map<String,String> map = new HashMap<String,String>();
//添加元素
map.put("郭靖","黄蓉");
map.put("杨过","小龙女");
map.put("张无忌","赵敏");
//获取所有键的集合
Set<String> set = map.keySet();
//遍历键的集合,获取到每一个键
for(String key : set) {
//根据键去找值
String value = map.get(key);
System.out.println(key+"---"+value);
}
}
}
方式二:键值对对象找键和值
- 思路:
- 获取所有键值对对象的集合
- 遍历键值对对象的集合,得到每一个键值对对象
- 根据键值对对象获取键和值
- 示例:
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class MapDemo2 {
public static void main(String[] args) {
//创建集合对象
Map<String,String> map = new HashMap<String,String>();
//添加元素
map.put("郭靖","黄蓉");
map.put("杨过","小龙女");
map.put("张无忌","赵敏");
//获取所有键值对对象的集合
//Set<Map.Entry<K,V>> entrySet()
//获取键值对对象的集合
Set<Map.Entry<String,String>> set = map.entrySet();
//遍历键值对对象的集合,得到每一个键值对对象
for(Map.Entry<String,String> me : set) {
//根据键值对对象获取键和值
String key = me.getKey();
String value = me.getValue();
System.out.println(key+"---"+value);
}
}
}
两种方式图解
嵌套集合
ArrayList嵌套HashMap
-
要求:
ArrayList集合嵌套HashMap集合并遍历;
定义一个ArrayList集合,它包含三个元素,每一个元素都是HashMap类型的 -
示例
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
public class ArrayListIncludeHashMapTest {
public static void main(String[] args) {
//创建集合对象
ArrayList<HashMap<String,String>> array = new ArrayList<HashMap<String,String>>();
//创建元素1
HashMap<String,String> hm1 = new HashMap<String,String>();
hm1.put("孙策","大乔");
hm1.put("周瑜","小乔");
//把元素添加到array中
array.add(hm1);
//创建元素2
HashMap<String,String> hm2 = new HashMap<String,String>();
hm2.put("郭靖","黄蓉");
hm2.put("杨过","小龙女");
//把元素添加到array中
array.add(hm2);
//创建元素3
HashMap<String,String> hm3 = new HashMap<String,String>();
hm3.put("令狐冲","任盈盈");
hm3.put("林平之","岳灵珊");
//把元素添加到array中
array.add(hm3);
//遍历ArrayList集合
for(HashMap<String,String> hm : array) {
Set<String> set = hm.keySet();
for(String key : set) {
String value = hm.get(key);
System.out.println(key+"---"+value);
}
System.out.println("-----------------");
}
}
}
HashMap嵌套ArrayList
-
要求:
HashMap集合嵌套ArrayList集合并遍历;
定义一个HashMap集合,它包含三个元素,每一个元素的键是String类型,值是ArrayList类型 -
示例:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;
public class HashMapIncludeArrayListTest {
public static void main(String[] args) {
//创建集合对象
HashMap<String,ArrayList<String>> hm = new HashMap<String,ArrayList<String>>();
//创建元素1
ArrayList<String> sgyy = new ArrayList<String>();
sgyy.add("诸葛亮");
sgyy.add("赵云");
//把元素添加到hm中
hm.put("三国演义", sgyy);
//创建元素2
ArrayList<String> xyj = new ArrayList<String>();
xyj.add("唐僧");
xyj.add("孙悟空");
//把元素添加到hm中
hm.put("西游记", xyj);
//创建元素3
ArrayList<String> shz = new ArrayList<String>();
shz.add("武松");
shz.add("鲁智深");
//把元素添加到hm中
hm.put("水浒传", shz);
//遍历集合
Set<String> set = hm.keySet();
for(String key : set) {
System.out.println(key);
ArrayList<String> value = hm.get(key);
for(String s : value) {
System.out.println("\t"+s);
}
}
}
}