先来看下集合的知识点总结框图:
1.双列集合Map Key-Value就是用来存粗这种键值映射关系的数据。
双列集合键是唯一的,一个键只能映射一个值,如果键相同,值覆盖
Map的所有数据结构只跟键有关,跟值没有关系。
Map集合的一些功能:
(1)添加功能:
V put(K key,V value);添加元素
(2)删除功能:
V remove(Object key);移除键对应的值
void clear();清除所有键值对元素
(3)判断功能
boolean containsKey(Object key);判断是否包含指定的键。
boolean containsValue(Object value);判断是否包含指定的值。
boolean isEmpty();判断是否为空
(4)获取功能
SetkeySet()获取键值集合;
Set<Map.Entry<K,V>> entrySet();获取键值对集合;
V get(Object key);根据键获取值
遍历方方式:键找值keySet;获取键值对对象Map.Entry;
public class Demo1 {
public static void main(String[] args) {
//Map集合存储双序列
//Map集合的功能:V put(K key,V value)添加元素
//void clear();移除所有的键值对元素
//V remove(Object key);根据键删除键值对元素
//判断功能:
// boolean containsKey(Object key);是否包含对应的键值
//boolean containsValue(Object value);是否包含指定的值
//boolean isEmpty();判断是否为空
//获取功能
//Set<Map.Entry<K,V>>entrySet();返回一个键值对的set集合
//V getValue(Object key);根据键获取值
//Set <K> keyset();获取集合中所有键的集合
HashMap<Integer,String> hashMap=new HashMap<>();
hashMap.put(1,"123");
hashMap.put(2,"456");
hashMap.put(3,"789");
hashMap.put(4,"098");
hashMap.put(1,"abc");//键相同,值覆盖
boolean b1=hashMap.containsKey(4);
System.out.println(b1);
boolean b2=hashMap.containsValue("123");
System.out.println(b2);
//遍历元素
//1,根据键找值
Set<Integer> keyset = hashMap.keySet();//一个存放键值的集合
for( Integer key:keyset){
String v = hashMap.get(key);
System.out.println(key + "=" + v);
}
//根据键值对找值
Set<Map.Entry<Integer,String>> entrySet=hashMap.entrySet();
for(Map.Entry<Integer,String> entries:entrySet){
Integer key=entries.getKey();
String value=entries.getValue();
System.out.println(key+"==="+value);
}
}
}
案例:Map存储自定义对象。
存储键是String,值是Student;
存储键是Student,值是String;Map集合所有的数据结构只跟键有关,键没有重写则键不唯一,需要重写hashCode()方法,equals()方法。
Map允许存储null值null键,但不能调用,能直接打印
public class Demo3 {
public static void main(String[] args) {
// 案例: HashMap集合键是Stirng值是Student的案例\
//在Student中必须重写toString()方法
HashMap<String,Student> hashMap=new HashMap<>();
hashMap.put("10",new Student("天天",12));
hashMap.put("20",new Student("亮亮",16));
hashMap.put("30",new Student("明明",13));
hashMap.put("40",new Student("欢欢",11));
hashMap.put("50",new Student("小小",10));
hashMap.put("60",new Student("乐乐",17));
hashMap.put("70",new Student("笑笑",16));
hashMap.put("12",new Student("天天",12));
Set<String> keySet=hashMap.keySet();
for(String key:keySet){
Student stu=hashMap.get(key);
System.out.println(key+"=="+stu.getName()+"=="+stu.getAge());
}
System.out.println("-------------------------");
Set<Map.Entry<String,Student>> entry=hashMap.entrySet();
for(Map.Entry<String,Student> entries:entry){
String key=entries.getKey();
Student stu=entries.getValue();
System.out.println(key+"=="+stu.getName()+"=="+stu.getAge());
}
}
}
public class Student implements Comparable<Student> {
private String name;
private int age;
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 compareTo(Student student){
int num=this.age-student.age;
int num2=(num==0)?this.name.compareTo(student.name):num;
return num2;
}
@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 class Demo4 {
public static void main(String[] args) {
// 存储键是Student,值是String
//必须重写Student中的hashCode()方法和equals方法,数据结构只跟
//键有关,跟值没有关系.
HashMap<Student,String> hashMap=new HashMap<>();
hashMap.put(new Student("天天",12),"s002");
hashMap.put(new Student("欢欢",10),"s003");
hashMap.put(new Student("明明",18),"s004");
hashMap.put(new Student("乐乐",16),"s005");
hashMap.put(new Student("笑笑",13),"s006");
hashMap.put(new Student("小小",12),"s007");
hashMap.put(new Student("壮壮",17),"s008");
hashMap.put(new Student("格格",15),"s009");
hashMap.put(new Student("天天",12),"s001");
//键找值
Set<Student> keyset=hashMap.keySet();
for(Student key:keyset){
String value=hashMap.get(key);
System.out.println(key.getName()+"==="+key.getAge()+"==="+value);
}
System.out.println("------------------------");
//键值对找值
Set<Map.Entry<Student,String>> entries=hashMap.entrySet();
for(Map.Entry<Student,String> entryset:entries){
Student key=entryset.getKey();
String value=entryset.getValue();
System.out.println(key.getName()+"===="+key.getAge()+"===="+value);
}
}
}
2.LinkedHashMap 元素有序且唯一,所有数据结构只跟键有关。
LinkedHashMap的底层数据结构是链表和哈希表,链表保证元素有序,哈希表保证元素唯一。
public class Demo5 {
public static void main(String[] args) {
//LinkedHashMap 元素有序,且唯一
LinkedHashMap<String ,String > linkedHashMap=new LinkedHashMap<>();
linkedHashMap.put("10","a");
linkedHashMap.put("20","b");
linkedHashMap.put("30","c");
linkedHashMap.put("40","d");
linkedHashMap.put("50","e");
linkedHashMap.put("60","f");
linkedHashMap.put("70","g");
linkedHashMap.put("40","d");
Set<String> keySet= linkedHashMap.keySet();
for(String key:keySet){
String value= linkedHashMap.get(key);
System.out.println(key+"====="+value);
}
System.out.println("-------------------------");
Set<Map.Entry<String,String>> entry= linkedHashMap.entrySet();
for(Map.Entry<String,String> entries:entry){
String key=entries.getKey();
String value=entries.getValue();
System.out.println(key+"===="+value);
}
}
}
3.TreeMap可以对键进行排序。
TreeMap的底层数据结构是红黑树,可以保证键的排序性和唯一性,排序分为自然排序和比较器排序;线程不安全,效率高。
案例 :键Student 值Integer 重写compare方法。
public class TreeHashMapDemo2 {
public static void main(String[] args) {
//TreeMap集合键是Student值是String的案例
// 按照年龄大小进行排序
//注意键要实现Comparable 接口
TreeMap<Student,String> treeMap=new TreeMap<>();
treeMap.put(new Student("天天",12),"ab");
treeMap.put(new Student("亮亮",16),"gh");
treeMap.put(new Student("明明",18),"ac");
treeMap.put(new Student("小小",11),"cj");
treeMap.put(new Student("默默",10),"cm");
treeMap.put(new Student("开开",19),"cmg");
treeMap.put(new Student("顶顶",23),"cgh");
treeMap.put(new Student("佳佳",19),"xg");
treeMap.put(new Student("天天",12),"abxsf");
Set<Student> keyset=treeMap.keySet();
for(Student stu:keyset) {
String value=treeMap.get(stu);
System.out.println(stu.getName()+"---"+stu.getAge()+"---"+value);
}
}
}
案例:键Integer 值Student
public class TreeSeMapDemo {
public static void main(String[] args) {
//TreeMap有序且唯一
//TreeMap集合键是Integer值是String的案例
TreeMap<Integer,String> treeMap=new TreeMap<>();
treeMap.put(1,"ab");
treeMap.put(6,"gh");
treeMap.put(8,"ac");
treeMap.put(12,"cj");
treeMap.put(65,"cm");
treeMap.put(67,"cmg");
treeMap.put(34,"cgh");
treeMap.put(3,"xg");
treeMap.put(1,"abxsf");
Set<Integer> keyset=treeMap.keySet();
for(Integer integer:keyset) {
String value=treeMap.get(integer);
System.out.println(integer+"---"+value);
}
}
}
//运行结果
// 1---abxsf
// 3---xg
// 6---gh
// 8---ac
// 12---cj
// 34---cgh
// 65---cm
// 67---cmg
- 案例演示: 需求:统计键盘随意输入一个字符串中每个字符出现的次数,例如:“aababcabcdabcde”,获取字符串中每一个字母出现的次数要求结果:a(5)b(4)c(3)d(2)e(1)。
分析:一个字符对应一个数值,故采用双列集合HashMap;
步骤(1).把字符串转成字符数组;(2).把数组中的字符当做键值传入到HashMap集合中,利用其键相同,值覆盖的特性统计字符出现的个数;(3)利用StringBuffer的append方法把字符连接起来存到StringBuffer中,,打印输出即可。
public class Demo1 {
public static void main(String[] args) {
// 案例演示: 需求:统计字符串中每个字符出现的次数
// "aababcabcdabcde",获取字符串中每一个字母出现的次数要求结果:a(5)b(4)c(3)d(2)e(1)
//分析:取出字符,一个字符对应一个统计数,采用双列集合,把字符当做键值,字符个数为值
Scanner sc=new Scanner(System.in);
System.out.println("请输入一串字符串:");
String s=sc.nextLine();
char[] chars=s.toCharArray();//字符串转为字符数组
HashMap<Character,Integer>hashMap=new HashMap<>();//char------Character
for(char c:chars){
if(!hashMap.containsKey(c)){
hashMap.put(c,1);
}else{
Integer value=hashMap.get(c);
value++;
hashMap.put(c,value);//键相同,值覆盖
}
}
//字符拼接组合 存放到StringBuffer中
StringBuffer stringBuffer = new StringBuffer();
Set<Character>keyset=hashMap.keySet();
for(Character key:keyset){
stringBuffer.append(key).append("(").append(hashMap.get(key)).append(")");
}
System.out.println(stringBuffer);
}
}
案例演示:集合嵌套之HashMap嵌套HashMap
public class Demo2 {
public static void main(String[] args) {
// 案例演示 :集合嵌套之HashMap嵌套HashMap
// 基础班
// 张三 20
// 李四 22
// 就业班
// 王五 21
// 赵六 23
HashMap<String,Integer> hashMap1= new HashMap<>();
hashMap1.put("张三",20);
hashMap1.put("李四",22);
HashMap<String,Integer> hashMap2= new HashMap<>();
hashMap2.put("王五",21);
hashMap2.put("赵六",23);
HashMap<String,HashMap<String,Integer>>hashMap=new HashMap<>();
hashMap.put("基础班",hashMap1);
hashMap.put("就业班",hashMap2);
Set<String> keyset=hashMap.keySet();
for(String key:keyset){
System.out.println(key);
HashMap<String,Integer> V=hashMap.get(key);
Set<String>keysetmin=V.keySet();
for(String keymin:keysetmin){
Integer v1=V.get(keymin);
System.out.println(" "+keymin+" "+v1);
}
}
}
}
案例演示:集合嵌套之HashMap嵌套ArrayList
假设HashMap集合的元素是ArrayList。有3个。
每一个ArrayList集合的值是字符串。
public static void main(String[] args) {
// 案例演示 集合嵌套之HashMap嵌套ArrayList
// 假设HashMap集合的元素是ArrayList。有3个每一个ArrayList集合的值是字符串。
// 三国演义
// 吕布
// 周瑜
// 笑傲江湖
// 令狐冲
// 林平之
// 神雕侠侣
// 郭靖
// 杨过
ArrayList<String> arrayList1= new ArrayList<>();
arrayList1.add("吕布");
arrayList1.add("周瑜");
ArrayList<String> arrayList2= new ArrayList<>();
arrayList2.add("令狐冲");
arrayList2.add("林平之");
ArrayList<String> arrayList3= new ArrayList<>();
arrayList3.add("郭靖");
arrayList3.add("杨过");
HashMap<String,ArrayList<String>> hashMap= new HashMap<>();
hashMap.put("三国演义",arrayList1);
hashMap.put("笑傲江湖",arrayList2);
hashMap.put("神雕侠侣",arrayList3);
Set<String>keyset=hashMap.keySet();
for(String key:keyset){
System.out.println(key);
ArrayList<String> value=hashMap.get(key);
for(String ele:value){
System.out.println(" "+ele);
}
}
}
}
案例演示:集合嵌套之ArrayList嵌套HashMap
public class Demo4 {
public static void main(String[] args) {
// 集合嵌套之ArrayList嵌套HashMap
// 假设ArrayList集合的元素是HashMap。有3个每一个HashMap集合的键和值都是字符串。
// 周瑜---小乔
// 吕布---貂蝉
//
// 郭靖---黄蓉
// 杨过---小龙女
//
// 令狐冲---任盈盈
// 林平之---岳灵珊
HashMap<String,String>hashMap1=new HashMap<>();
hashMap1.put("周瑜","小乔");
hashMap1.put("吕布","貂蝉");
HashMap<String,String>hashMap2=new HashMap<>();
hashMap2.put("郭靖","黄蓉");
hashMap2.put("杨过","小龙女");
HashMap<String,String>hashMap3=new HashMap<>();
hashMap3.put("令狐冲","任盈盈");
hashMap3.put("林平之","岳灵珊");
ArrayList<HashMap<String,String>>arrayList=new ArrayList<>();
arrayList.add(hashMap1);
arrayList.add(hashMap2);
arrayList.add(hashMap3);
for(HashMap<String,String> hm:arrayList){
Set<String>keyset=hm.keySet();
for(String key:keyset){
String value=hm.get(key);
System.out.println(key+"----"+value);
}
}
}
- 类 Hashtable<K,V> 此类实现一个哈希表,该哈希表将键映射到相应的值。任何非 null 对象都可以用作键或值
注意:HashMap与Hashtable的区别:
Hashtable 不允许null值与null键;线程安全,效率低;
HashMap: 线程不安全,效率高.允许null值和null键。
7.Coolection集合的工具类:Collections类
Collections类概述: 针对集合操作 的工具类
Collections成员方法
public static void sort(List list):排序,默认按照自然顺序
public static int binarySearch(List<?> list,T key):二分查找
public static T max(Collection<?> coll):获取最大值
public static void reverse(List<?> list): 反转
public static void shuffle(List<?> list): 随机置换
8.lambda表达式;Stream流,(JDK1.8新特性):
Lambda表达式是一个可以传递的代码块,可以在以后执行一次或多次。
语法:参数->表达式
例如:(String first,String second)->first.length()-sencond.length();
public class Demo5 {
public static void main(String[] args) {
//Collections 工具类,对集合进行操作的工具类
//Collections中的一些功能方法:
//public static<T>void sort(List<T>list);排序,默认的自然排序
// int binarySrarch(List<T>list,T key);二分查找
// T max(Collection<?>coll);获取最大值
// public static void reverse(List<T>list);反转
//public static void shuffle(List<T>list);反转
//public static<T>void sort(List<T>list,Comparator<? super T>c)
ArrayList<Integer>arrayList=new ArrayList<>();
arrayList.add(10);
arrayList.add(1);
arrayList.add(15);
arrayList.add(18);
arrayList.add(2);
arrayList.add(23);
Collections.sort(arrayList);
System.out.println(arrayList);
Collections.reverse(arrayList);
System.out.println(arrayList);
Collections.shuffle(arrayList);
System.out.println(arrayList);
Collections.sort(arrayList,(x,y)->-(x-y));//lambda表达式,返回的为负的前一个数减去第二个数,
// 即从大到小排序
System.out.println(arrayList);
System.out.println(Collections.max(arrayList));
}
}
案例演示:1. 模拟斗地主洗牌和发牌
public class PokerGame2 {
public static void main(String[] args) {
HashMap<Integer,String>hashMap=new HashMap<>();
String[] num={"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
String[] color={"♥", "♠", "♦", "♣"};
ArrayList<String> arrayList=new ArrayList<>();
ArrayList<Integer> arrayListIndex=new ArrayList<>();
for(String n:num){
for(String c:color){
arrayList.add(n.concat(c));
}
}
//产生大小王
arrayList.add("?");//月亮代表小王
arrayList.add("☀");//太阳代表大王
//把牌存到双列集合HashMap中,键与元素一一对应,把键单独存到ArrayLiast中进行洗牌
for(int i=0;i<54;i++){
hashMap.put(i,arrayList.get(i));
arrayListIndex.add(i);
}
//洗牌
//洗牌(洗三次)
Collections.shuffle(arrayListIndex);
Collections.shuffle(arrayListIndex);
Collections.shuffle(arrayListIndex);
//发牌(采用TreeSet对键进行排序,从而相当于对值进行排序)
TreeSet<Integer> person1=new TreeSet<>();
TreeSet<Integer> person2=new TreeSet<>();
TreeSet<Integer> person3=new TreeSet<>();
TreeSet<Integer> diPai=new TreeSet<>();
for(int i=0;i<arrayListIndex.size();i++){
if(i>=arrayListIndex.size()-3){
Integer integer=arrayListIndex.get(i);
diPai.add(integer);
}else if(i%3==0){
Integer integer1=arrayListIndex.get(i);
person1.add(integer1);
}else if(i%3==1){
Integer integer2=arrayListIndex.get(i);
person2.add(integer2);
}else if(i%3==2){
Integer integer3=arrayListIndex.get(i);
person3.add(integer3);
}
}
//看牌
LookPoker("Person1",person1,hashMap);
LookPoker("Person2",person2,hashMap);
LookPoker("Person3",person3,hashMap);
LookPoker("diPai",diPai,hashMap);
}
private static void LookPoker(String name, TreeSet<Integer> setkey, HashMap<Integer,String> hashMap) {
System.out.println(name);
for(Integer key:setkey){
System.out.print(hashMap.get(key)+" ");
}
System.out.println();
}
}
9.异常:
Throwable是错误和异常的父类;
Error严重的问题,无法解决,例如内存溢出。
Exception异常,我们可以处理:分为编译期异常 和 运行期异常
编译期异常:必须解决; 运行期异常:可以解决可以不解决。
(1)运行期异常:RuntimeException及其子类;
运行期异常如果我们没有处理,默认交由JVM去处理,JVM打印出异常信息,然后退出虚拟机。
当不希望是默认处理方式,需要自己处理:使用try catch
Try中放一些可能会出现异常的代码,try里面的代码一旦出现异常,就会执行catch里面的代码;
Try {
可能出现问题的代码 ;
}catch(异常名 变量名){
针对问题的处理 ;
}
多个异常,如果是平级关系异常,谁前谁后无所谓,如果多个异常有父子关系,那么父级别的异常放在最后面。
Catch里面不要做空处理,哪怕简单的输出一条语句。
运行时期的一些异常案例:
(2)编译期异常,必须处理,否则程序无法运行。
编译期异常:处理 方式1:向上抛,谁调用谁处理;throws抛出异常;
方式2:try catch
(3)注意:throw与throws的区别:
throw用在方法内部,跟的是异常对象名,只能抛出一个异常对象名;这个异常对象名可以是运行期的,也可以是编译期的,表示抛出异常由方法体内的语句处理,throw则是一定抛出了某种异常。
throws用在方法声明的后面,跟的是异常类名;可以跟多个异常类名,用逗号隔开,表示抛出异常,由调用方法者处理。throws表示异常的一种可能性,并不一定会发生异常。
(4)finally关键字
finally最终要执行的,不管你try里面的代码有没有遇到异常,Finally里面的代码都执行。一般会在finally里面做一些善后收尾工作,比如释放一些资源。
(5). final,finally和finalize的区别
final: 是一个状态修饰符, 可以用来修饰类 , 变量 , 成员方法. 被修饰的类不能被子类继承, 修饰的变量其实是一个常量不能被再次赋值修饰的方法不能被子类重写。
finally:用在try…catch…语句中 , 作用: 释放资源 . 特点: 始终被执行(JVM不能退出)。
finalize: Obejct类中的一个方法,用来回收垃圾。
(6)自定义异常:Java提供的异常是有限的,就需要我们自定义异常。
需要将我们自定义的异常类纳入到我们的异常体系中:
继承自Exception
继承自RuntimeException
案例: 考试成绩必须在0-100之间,不满足就产生异常。
10.(1)子类在重写父类方法是,父类的方法没有抛出过异常,子类重写的方法也不能抛出异常,异常要try掉。
(2)父类子类都抛异常时,子类抛出的异常不能比父类的大,要么比父类小,要么和父类一样。
(3)如果父类抛出了多个异常,子类重写父类方法时,子类的方法必须抛出相同的异常或父类异常的子类,或者子类不抛出异常也是可以的。