集合框架与泛型
前言
使用Map存取数据,掌握泛型的使用,Collections的使用
一、Map接口与HashMap类
Map接口专门处理键值映射数据的存储,可以根据键实现对值的操作
最常用的实现类是HashMap
HashMap常用方法
二、遍历Map集合
1)通过迭代器Iterator实现遍历
2)增强for循环
3)键值对
public static void main(String[] args) {
// 准备容器
HashMap hashMap = new HashMap();
// 调用方法将字符串类型的键和值存储在集合中
hashMap.put("CN", "中国");
hashMap.put("USA", "美国");
hashMap.put("UK", "英国");
hashMap.put("RU", "俄罗斯");
hashMap.put("JP", "日本");
// 获取集合中元素个数
System.out.println("集合中元素个数:" + hashMap.size()); // 集合中元素个数:5
// 判断集合是否为空
System.out.println("集合为空:" + hashMap.isEmpty()); // 集合为空:false
/*
* HashMap集合存储数据,例如存储身份证号码和姓名,存储唯一,无序的对象,用键值更加便捷
* 集合框架不同就根据需求选择应用
*/
// 获取集合中的某一个元素,根据键来获取值
Object obj1 = hashMap.get("CN");
String value1 = (String) obj1;
System.out.println(value1); // 中国
Object obj2 = hashMap.get("USA");
String value2 = (String) obj2;
System.out.println(value2); // 美国
System.out.println("------ ------ ------");
// 遍历Map集合:因为要获取值,需要通过键来获取,所以先获取所有的键,然后遍历键去获取值
// Set<k> keySet():返回此映射中包含的键的Set视图
Set keySet = hashMap.keySet();
// 遍历keySet集合,一个一个的取出里面的键
for (Object objKey : keySet) {
String key = (String) objKey;
// 根据键获取值
Object objValue = hashMap.get(key);
String value = (String) objValue;
System.out.println(key + "---" + value);
}
// 输出结果
// USA---美国
// RU---俄罗斯
// UK---英国
// JP---日本
// CN---中国
System.out.println("------ ------ ------");
// 获取了所有的键之后,可以使用迭代器遍历键的集合
/*
* boolean hasNext()如果仍有元素可以迭代,则返回 true
* E next()返回迭代的下一个元素
*/
Iterator keyIterator = keySet.iterator();
while (keyIterator.hasNext()) {
Object objKey = keyIterator.next();
String key = (String) objKey;
// 根据键获取值
Object objValue = hashMap.get(key);
String value = (String) objValue;
System.out.println(key + "---" + value);
}
System.out.println("------ ------ ------");
// 直接从Map集合中遍历键值对
// keyValue集合中存储的是Map里面的键值对数据,这个键值对数据的类型为Map.Entry
Set keyValue = hashMap.entrySet();
for (Object object : keyValue) {
// 键值对的类型转换为起真实类型Map.Entry
Map.Entry me = (Map.Entry) object;
// 使用me对象调用方法获取键值对里的键
Object keyObj = me.getKey();
String key = (String) keyObj;
// 使用me对象调用方法获取键值对里的值
Object valueObj = me.getValue();
String value = (String) valueObj;
System.out.println(key + "---" + value);
}
}
}
public class HashMapDemo02 {
public static void main(String[] args) {
// 准备容器
HashMap hashMap = new HashMap();
// 调用方法将字符串类型的键和值存储在集合中
hashMap.put("CN", "中国");
hashMap.put("USA", "美国");
hashMap.put("UK", "英国");
hashMap.put("RU", "俄罗斯");
hashMap.put("JP", "日本");
// 获取集合中元素个数
System.out.println("集合中元素个数:" + hashMap.size()); // 集合中元素个数:5
// 移除JP
Object obj1 = hashMap.remove("JP");
System.out.println("移除JP对应的国家是:" + obj1); // 移除JP对应的国家是:日本
// 获取集合中的元素个数
System.out.println("集合中元素个数:" + hashMap.size()); // 集合中元素个数:4
System.out.println("------ ------ ------");
// 获取集合中所有的值
Collection values = hashMap.values();
// 遍历values集合可以使用增强for循环或迭代器
for (Object object : values) {
String value = (String) object;
System.out.println(value);
}
// 输出结果
// 美国
// 俄罗斯
// 英国
// 中国
System.out.println("------ ------ ------");
// 判断集合中是否包含指定的键
System.out.println("集合中包含JP这个键:" + hashMap.containsKey("JP")); // 集合中包含JP这个键:false
System.out.println("集合中包含RU这个键:" + hashMap.containsKey("RU")); // 集合中包含RU这个键:true
// 判断集合中是否包含指定的值
System.out.println("集合中包含日本国这个值:" + hashMap.containsValue("日本")); // 集合中包含日本国这个值:false
System.out.println("集合中包含俄罗斯联邦这个值:" + hashMap.containsValue("俄罗斯")); // 集合中包含俄罗斯联邦这个值:true
}
}
public class Student {
private String name;
private char gender;
public Student() {
}
public Student(String name, char gender) {
this.name = name;
this.gender = gender;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", gender=" + gender +
'}';
}
}
public class HashMapDemo01 {
public static void main(String[] args) {
// 准备数据:创建3个Student对象
Student student1 = new Student("张三", '男');
Student student2 = new Student("李四", '男');
Student student3 = new Student("如花", '男');
// 准备容器,存储Student对象
HashMap hashMap = new HashMap();
// 将数据存储到集合中
hashMap.put("Jack", student1);
hashMap.put("Bob", student3);
hashMap.put("lisa", student2);
// 获取英文名称Bob的学员信息
Object value = hashMap.get("Bob");
System.out.println(value); // Student{name='如花', age=30007}
// toString()方法Object类中的方法,查看该方法的原码知道
// 该方法输出的是兑现在内存中的地址值,我们可以在子类中对该方法进行重写,输出对象的属性信息
System.out.println(value.toString());
// 如果只需要获取学员对象的姓名,只能通过Student类对象调用getName()方法,value对象不能调用Student类中的getName()方法
Student stu = (Student) value;
System.out.println("Bob对应的学员姓名:" + stu.getName()); // Bob对应的学员姓名:如花
System.out.println("------ ------ ------");
// 使用增强for循环遍历所有学员的姓名
Set keys = hashMap.keySet();
// 遍历keys集合
for (Object object : keys) {
// 将键转换为真实类型String
String key = (String) object;
// 根据键获取值
Object objValue = hashMap.get(key);
// 将值转换为真实的类型Student
Student student = (Student) objValue;
System.out.println(key + "-" + student.getName());
}
System.out.println("------ ------ ------");
// 使用迭代器循环遍历所有学员的姓名
Iterator keyIterator = keys.iterator();
while (keyIterator.hasNext()) {
Object objkey = keyIterator.next();
String key = (String) objkey;
// 根据键获取值
Object objValue = hashMap.get(key);
Student student = (Student) objValue;
System.out.println(key + "-" + student.getName() + "-" + student.getGender());
}
System.out.println("------ ------ ------");
// 使用键值对遍历所有学员的姓名
Set keyValues = hashMap.entrySet();
for (Object object : keyValues) {
// 键键值对的类型转换为真实类型Map.Entry
Map.Entry me = (Map.Entry) object;
// 获取键
Object objKey = me.getKey();
// 将键转换为真实类型String
String key = (String) objKey;
// 获取值
Object objValue = me.getValue();
// 将值转换为真实类型Student
Student student = (Student) objValue;
System.out.println(key + "-" + student.getName());
}
}
}
三、泛型集合
问题:如何解决以下强制类型转换时容易出现的异常问题
1)List的get(int index)方法获取元素
2)Map的get(Object key)方法获取元素
3)Iterator的next()方法获取元素
解答:通过泛型
在JDK5.0中使用泛型改写了集合框架中的所有接口和类
1、泛型的概念
将对象的类型作为参数,指定到其他类或方法上,从而保证类型转换的安全性和稳定性
本质是参数化类型
2、泛型集合
泛型集合可以约束集合内的元素类型
典型泛型集合ArrayList<>、HashMap<K,V>
1)<>、<K,V>表示该泛型集合中的元素类型
2)泛型集合中的数据不再转换为Object
除了指定了集合中的元素类型外,泛型集合和之前学习的集合用法完全一样
package javaapidemo0125.demo04;
public class Student {
private String name;
private char gender;
public Student() {
}
public Student(String name, char gender) {
this.name = name;
this.gender = gender;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", gender=" + gender +
'}';
}
}
package javaapidemo0125.demo04;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class HashMapDemo01 {
public static void main(String[] args) {
// 创建3个Student对象
Student student1 = new Student("张三", '男');
Student student2 = new Student("李四", '男');
Student student3 = new Student("如花", '女');
// 准备容器,存储上面3个Student类对象
// HashMap hashMap = new HashMap();
// 使用泛型
HashMap<String, Student> hashMap = new HashMap<String, Student>();
// 将数据存储到集合中
hashMap.put("Jack", student1);
hashMap.put("Bob", student2);
hashMap.put("Lisa", student3);
// 获取英文名为Bob的学员信息
/*Object object = hashMap.get("Bob");
System.out.println(object); // Student{name='李四', gender=男}
Student s1 = (Student)object; // 向下转型
System.out.println(s1); // Student{name='李四', gender=男}
System.out.println(s1.toString()); // Student{name='李四', gender=男}
System.out.println(s1.getName()); // 李四
System.out.println(s1.getGender()); // 男*/
// 使用泛型
Student student = hashMap.get("Bob");
System.out.println(student); // Student{name='李四', gender=男}
System.out.println(student.getName()); // 李四
System.out.println("------ ------ ------");
// 使用增强for循环遍历所有学员姓名
// 遍历Map集合因为要获取值,需要通过键来获取,所以先获取所有的键,然后遍历键去获取值
// Set<K> keySet()返回此映射中所包含的键的Set视图
Set<String> keys = hashMap.keySet();
// 遍历键来获取值
for (String key : keys) {
Student students = hashMap.get(key);
// System.out.println(key + "-" + students);
System.out.println(key + "-" + students.getName());
// Bob-李四 Jack-张三 Lisa-如花
}
System.out.println("------ ------ ------");
// 获取键之后使用迭代器遍历键的集合
Iterator<String> keyIterator = keys.iterator();
// boolean hasNext()如果仍有元素可以迭代,则返回 true
while (keyIterator.hasNext()) {
// E next()返回迭代的下一个元素
String key = keyIterator.next();
// 根据键获取值
Student students = hashMap.get(key);
System.out.println(key + "-" + students.getName() + "-" + students.getGender());
// Bob-李四-男 Jack-张三-男 Lisa-如花-女
}
System.out.println("------ ------ ------");
// 使用键值对遍历
// hashMap.entrySet()是将Map中的键值对放在Set中,键值对类型是entry
Set<Map.Entry<String, Student>> keyValues = hashMap.entrySet();
for (Map.Entry<String, Student> me : keyValues) {
// 获取键
String key = me.getKey();
// 获取值
Student students = me.getValue();
System.out.println(key + "-" + students.getName() + "-" + students.getGender());
// Bob-李四-男 Jack-张三-男 Lisa-如花-女
}
/*
泛型使用总结:
没有使用泛型前,集合会将存入进去的元素都向上转型变为Object类型,那么再取出来的时候也是Object类型
这时候需要使用向下转型,将取出来的元素转换成其真实类型,才能调用对象中特有的方法
那么在向下转型过程中,容易出现ClassCastException(类型转换异常),当然你可以使用instanceof运算符进行类型判断,比较繁琐
因此,可以使用泛型来明确声明集合中只能存储的数据类型(相当于将集合变成了一个长度可变的数组),这个集合中就只能存储你指定的数据类型
你存进去的是指定的数据类型,那么取出来的也是你指定的类型,此时就不需要进行向下转型,减少向下转型过程汇总可能出现的类型转换异常
*/
}
}
四、Collections算法类
Java集合框架将针对不同数据结构算法的实现都保存在工具类中
Collections类定义了一系列用于操作集合的静态方法
Collections类常用方法
Collections和Collection不同,前者是集合的操作类,后者是集合接口
1)sort()排序
2)binarySearch()查找
3)max()\min()查找最大值最小值
Collections排序
1)Colleciotns类可以对集合进行排序、查找和替换操作
2)实现一个类的对象之间比较大小,该类要实现Comparable接口
重写compareTo()方法
package javaapidemo0125.demo05;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
public class CollectionsDemo01 {
public static void main(String[] args) {
// 创建ArrayList集合对象
ArrayList<String> stringArrayList = new ArrayList<String>();
// 向集合中存储数据
stringArrayList.add("hwert1");
stringArrayList.add("gwert2");
stringArrayList.add("fwert3");
stringArrayList.add("erwert4");
stringArrayList.add("dwert5");
stringArrayList.add("cwert6");
stringArrayList.add("bwert7");
stringArrayList.add("awert8");
System.out.println("集合排序前元素顺序:");
for (String string : stringArrayList) {
System.out.print(string + " ");
}
// sort()方法:升序排序集合中元素
Collections.sort(stringArrayList);
System.out.println("\n集合排序前后元素顺序:");
for (String string : stringArrayList) {
System.out.print(string + " ");
}
System.out.println();
/*
binarySearch()方法查找集合中的元素,在使用此方法之前,要求对集合中的元素进行升序排序,否则无法保证查询结果的正确性
返回查找元素的下标,如果查找的元素在集合中不存在,返回一个负值
*/
int index1 = Collections.binarySearch(stringArrayList, "awert8");
System.out.println("qwert在集合中的位置:" + index1);
int index2 = Collections.binarySearch(stringArrayList, "aaaaa");
System.out.println("aaaaa在集合中的位置:" + index2);
// max()\min()查找最大值/最小值
String max = Collections.max(stringArrayList);
String min = Collections.min(stringArrayList);
System.out.println("集合中的最大值:" + max);
System.out.println("集合中的最小值:" + min);
// 反转集合中的元素顺序
Collections.reverse(stringArrayList);
System.out.println("反转集合后元素顺序:");
for (String string : stringArrayList) {
System.out.print(string + " ");
}
}
}
public class Student implements Comparable<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 String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Student student) {
// 比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数
// 根据Student类对象年龄进行排序
if (this.getAge() < student.getAge()) {
return -1;
} else if (this.getAge() == student.getAge()) {
return 0;
} else {
return 1;
}
}
}
import java.util.Collections;
import java.util.LinkedList;
public class CollectionsDemo02 {
public static void main(String[] args) {
LinkedList<Student> studentLinkedList = new LinkedList<Student>();
// 创建4个Student类对象
Student student1 = new Student("张三", 25);
Student student2 = new Student("李四", 28);
Student student3 = new Student("王五", 24);
Student student4 = new Student("赵六", 26);
// 存储数据
studentLinkedList.add(student1);
studentLinkedList.add(student2);
studentLinkedList.add(student3);
studentLinkedList.add(student4);
// 遍历集合
System.out.println("排序前:");
for (Student student : studentLinkedList) {
System.out.println(student);
}
System.out.println("------ ------ ------");
// 对集合中元素进行排序
Collections.sort(studentLinkedList);
/*
public static <T extends Comparable<? super T>> void sort(List<T> list)根据元素的自然顺序 对指定列表按升序进行排序
public static <T> void sort(List<T> list,Comparator<? super T> c)根据指定比较器产生的顺序对指定列表进行排序
java.lang 接口 Comparable<T> 类型参数:T - 可以与此对象进行比较的那些对象的类型
int compareTo(T o) 比较此对象与指定对象的顺序
*/
System.out.println("排序后:");
for (Student student : studentLinkedList) {
System.out.println(student);
}
}
}