java从零开始系统性学习完整超全资源+笔记(下)
java从零开始系统性学习完整超全资源+笔记(下)
java从零开始系统性学习完整超全资源+笔记(上)
文章目录
- java从零开始系统性学习完整超全资源+笔记(下)
- 第十七章 泛型与常见数据结构
- ArrayList
- Collection接口的实现
- 泛型 generics
- 迭代器Iterator
- foreach
- 常见的数据结构
- 数组
- 链表
- 栈和队列
- List
- LinkedList
- 案例 查找元素索引及判断元素是否存在案例
- 练习
- 第十八章 Set与Map集合
- Set
- 增强for循环
- hashSet
- 方法重载与重写
- hashCode方法和equals方法的优化
- Collection
- 定义
- Collection和Collections有什么区别?
- collection方法
- Collection练习 模拟斗地主
- Map
- Map和Collection有什么区别?
- map常用功能
- map的两种遍历方式
- Map的第二种遍历方式
- 使用HashMap存储数据并遍历(字符串作为key)
- 使用HashMap存储数据并遍历(自定义对象作为key)
- 异常的处理
- 异常的概述和体系结构.
- JVM处理异常的方式
- 如何处理多个异常
- Throwable的常用方法
- finally概述和应用场景
- 异常的分类
- 自定义异常
- 递归概述和例题
第十七章 泛型与常见数据结构
ArrayList
集合的体系结构:
由于不同的数据结构(数据的组织,存储方式),所以Java为我们提供了不同的集合,
但是不同的集合他们的功能都是相似,不断的向上提取,将共性抽取出来,这就是集合体系结构形成的原因
体系结构:
怎么学习?最顶层开始学习,因为最顶层包含了所有的共性
怎么使用?使用最底层,因为最底层就是具体的实现
Collection
List
ArrayList
package com.demo01;import java.util.ArrayList;/** ArrayList* 集合的体系结构:* 由于不同的数据结构(数据的组织,存储方式),所以Java为我们提供了不同的集合,* 但是不同的集合他们的功能都是相似,不断的向上提取,将共性抽取出来,这就是集合体系结构形成的原因* * 体系结构:* 怎么学习?最顶层开始学习,因为最顶层包含了所有的共性* 怎么使用?使用最底层,因为最底层就是具体的实现* * Collection* List* ArrayList*/
public class CollectionDemo {public static void main(String[] args) { //创建集合对象ArrayList al = new ArrayList();//添加元素al.add("hello");al.add("world");al.add("java");//遍历集合for(int x = 0;x < al.size();x++) {System.out.println(al.get(x));}}
}
Collection接口的实现
Collection 层次结构 中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。JDK 不提供此接口的任何直接 实现:**它提供更具体的子接口(如 Set 和 List)**实现。此接口通常用来传递 collection,并在需要最大普遍性的地方操作这些 collection。
/** Collection接口的实现* boolean add(E e) 确保此 collection 包含指定的元素(可选操作)。* void clear() 移除此 collection 中的所有元素(可选操作)。* boolean contains(Object o) 如果此 collection 包含指定的元素,则返回 true。* boolean isEmpty() 如果此 collection 不包含元素,则返回 true。* boolean remove(Object o) 从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。* int size() 返回此 collection 中的元素数。* Object[] toArray() 返回包含此 collection 中所有元素的数组。* 如果此 collection 包含指定的元素,则返回 true。更确切地讲,当且仅当此 collection 至少包含一个满足 (o==null ? e==null : o.equals(e)) 的元素 e 时,返回 true。*/
package CollectionDemo;import java.util.ArrayList;
import java.util.Objects;public class ArrayListDemo2 {public static void main(String[] args) {ArrayList a = new ArrayList();
// 1.boolean add(E e)a.add("hello1"); //add的时候运行没有东西,必须打印出来才有a.add("hello2");
// 2.void clear()
// a.clear();for(int i = 0;i<a.size();i++){System.out.println(a.get(i));}
// 3.boolean contains(Object o)boolean flag = a.contains("hello1"); //包含就返回trueSystem.out.println(flag);System.out.println(a);
// boolean isEmpty()boolean flag1 = false;if(a!=null&&a.isEmpty()){flag1 = true;System.out.println(flag);}
// boolean remove(Object o)boolean f = a.remove("hello1");System.out.println(f);System.out.println(a);int size = a.size();System.out.println(size);
// Object[] toArray()Object[] objects = a.toArray();for(int i = 0;i< objects.length;i++){System.out.println(objects[i]);}}
}
泛型 generics
使用集合存储自定义对象并遍历* 由于集合可以存储任意类型的对象,当我们存储了不同类型的对象,就有可能在转换的时候出现类型转换异常,* 所以java为了解决这个问题,给我们提供了一种机制,叫做泛型* * 泛型:是一种广泛的类型,把明确数据类型的工作提前到了编译时期,借鉴了数组的特点* 泛型好处:* 避免了类型转换的问题* 可以减少黄色警告线* 可以简化我们代码的书写 不用强制类型转换* * 什么时候可以使用泛型?* 问API,当我们看到<E>,就可以使用泛型了List ArrayList Collection 等都可以用泛型使用泛型的缺点
虽然泛型在很多情况下能够提供强类型检查和代码重用的好处,但它们也有一些缺点,包括以下几点:**增加代码复杂性**:泛型代码通常比非泛型代码更复杂,因为它需要在类型安全的同时支持多种数据类型。这可能导致代码更难理解和维护。**增加编译时间**:泛型代码通常需要更多的编译时间,因为编译器必须在编译时生成并检查泛型类型的代码。这可能会导致较长的编译时间,特别是在使用大量泛型的大型项目中。受限于类型擦除:在 Java 中,泛型类型信息在编译时被擦除,这意味着在运行时无法访问泛型类型的信息。这可以导致一些类型转换和类型安全问题,尤其是在处理复杂的泛型类型时。需要额外的学习和使用成本:泛型是一种相对较新的编程技术,因此需要额外的学习成本。此外,对于一些简单的应用程序,使用泛型可能是过度设计,这可能会增加使用成本和复杂性。综上所述,泛型的使用虽然有很多好处,但也需要仔细考虑其使用场景和实际需求,以平衡其优点和缺点。
例如

package CollectionDemo;import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;/*泛型概述
使用集合可以存储任意类型的对象,由于存储了不同类型的对象,有可能在转换的时候
出现类型转换异常。所以java为了解决这个问题,提供了一种机制generic泛型
泛型:是一种广泛的类型,把明确数据类型的工作提前到了编译时期,借鉴了数组的特点
泛型的好处:避免类型转换的问题可以减少黄色警告线简化代码书写 不用强制类型转换
什么时候用泛型?问API,当我们看到就可以使用泛型List ArrayList Collection等都可以用泛型*/
public class GenericDemo {public static void main(String[] args) {
/*
// 不知道集合里面的类型是什么,所以用泛型解决这个问题
// Iterator 是一个接口,用于遍历集合(如 List、Set、Map 等)中的元素Collection c = new ArrayList();c.add("hello");Iterator iterator = c.iterator();int i = (int) iterator.next();System.out.println(i);
//出现异常 java.lang.String cannot be cast to java.lang.Integer
*/// 创建集合对象Collection<Student> c = new ArrayList<Student>();
// 创建元素对象Student s1 = new Student("zhangsan1",13);Student s2 = new Student("zhangsan2",16);
// 添加元素对象c.add(s1);c.add(s2);
// 遍历元素对象Iterator<Student> it = c.iterator();while (it.hasNext()){Student stu = it.next();System.out.println(stu.name);}}static class Student{String name;int age;public Student(String name,int age){this.name = name;this.age = age;}}
}
package com.demo03;import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;/** 使用集合存储自定义对象并遍历* 由于集合可以存储任意类型的对象,当我们存储了不同类型的对象,就有可能在转换的时候出现类型转换异常,* 所以java为了解决这个问题,给我们提供了一种机制,叫做泛型* * 泛型:是一种广泛的类型,把明确数据类型的工作提前到了编译时期,借鉴了数组的特点* 泛型好处:* 避免了类型转换的问题* 可以减少黄色警告线* 可以简化我们代码的书写 不用强制类型转换* * 什么时候可以使用泛型?* 问API,当我们看到,就可以使用泛型了List ArrayList都可以用泛型* */
public class GenericDemo {public static void main(String[] args) {/* Collection c = new ArrayList();c.add("Hello");Iterator iterator = c.iterator();int i = (int) iterator.next();System.out.println(i);*/ //String[] s =new String[3];//创建集合对象Collection<Student> c = new ArrayList<Student>();//创建元素对象Student s = new Student("zhangsan",18);Student s2 = new Student("lisi",19);//添加元素对象c.add(s);c.add(s2);//遍历集合对象Iterator<Student> it = c.iterator();while(it.hasNext()) {Student stu = it.next();System.out.println(stu.name);}}
}class Student {String name;int age;public Student(String name,int age) {this.name = name;this.age = age;}
}
迭代器Iterator
chatGPT回答
在 Java 中,Iterator 是一个接口,用于**遍历集合(如 List、Set、Map 等)中的元素**。Iterator 接口定义了访问和移除集合中元素的方法,可以帮助开发者逐个访问集合中的元素,而不需要暴露底层数据结构的实现细节。Iterator 接口包含以下几个方法:hasNext():返回集合中是否还有下一个元素。
next():返回下一个元素。
remove():从集合中移除上一次返回的元素(可选操作)。
使用 Iterator 遍历集合的基本流程是:首先通过集合对象的 iterator() 方法获得 Iterator 实例,然后通过调用 hasNext() 和 next() 方法逐个访问集合中的元素,最后使用 remove() 方法删除元素(如果需要)。Iterator 接口的出现使得遍历集合变得更加方便和灵活,同时也提高了代码的可读性和可维护性。
在使用迭代器进行遍历的时候使用迭代器来进行修改

iterator() 可以返回一个迭代器对象,我们可以通过迭代器对象来迭代集合
- Iterator:可用于遍历集合
- E next()返回下一个元素
- boolean hasNext():判断元素是否可以获取
package CollectionDemo;import java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;/*
* 集合的遍历方式
* 1.toArray() 可以将集合转化成数组,然后遍历数组即可
* 2.iterator() 可以返回一个迭代器对象,我们可以通过迭代器对象来迭代集合
* Iterator:可用于遍历集合
* E next()返回下一个元素
* boolean hasNext():判断元素是否可以获取
* 注意:Exception in thread "main" java.util.NoSuchElementException
* 使用next方法获取下一个元素,如果没有元素可以获取,则出现NoSuchElementException
* */
public class IteratorDemo1 {public static void main(String[] args) {
// 创建集合对象Collection c = new ArrayList();
// 添加元素c.add("hello1");c.add("hello2");
// 获取数组Object[] objs = c.toArray();
// 遍历数组for (int i = 0; i < objs.length; i++) {System.out.println(objs[i]);}}
}
/*运行结果
hello1
hello2
*/
package CollectionDemo;import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;public class IteratorDemo2 {public static void main(String[] args) {//创建集合对象Collection c = new ArrayList();//添加元素c.add("hello1");c.add("hello2");
// 获取迭代器对象Iterator it = c.iterator();
// Object next():返回下一个元素/* System.out.println(it.next());System.out.println(it.next());
// 输出hello1,hello2*/// boolean hasNext():判断是否有元素可以获取/* if(it.hasNext()){System.out.println(it.next());} //输出hello1*/while (it.hasNext()){System.out.println(it.next());} //输出 hello1 hello2}
}
package CollectionDemo;import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;/*需求:判断集合中是否包含元素java,如果有则添加元素android
Exception in thread "main" java.util.ConcurrentModificationException:并发修改异常
迭代器是依赖集合的,相当于集合的一个副本,当迭代器在操作的时候如果发现和迭代器不一样就抛出异常
解决方案:别使用迭代器在使用迭代器进行遍历的时候使用迭代器来进行修改
* */
public class IteratorDemo3 {public static void main(S,,,,,,,,,,,,,,,tring[] args) {
// 创建集合对象List c = new ArrayList();
// 添加元素c.add("hello1");c.add("hello2");c.add("java");System.out.println(c);
// 通过遍历集合中的每一个元素来比较判断是否包含java/* Iterator it = c.iterator();while (it.hasNext()){String s = (String) it.next();if(s.equals("java")){c.add("android");}}System.out.println(c);Exception in thread "main" java.util.ConcurrentModificationException:并发修改异常
迭代器是依赖集合的,相当于集合的一个副本,当迭代器在操作的时候如果发现和迭代器不一样就抛出异常*/ListIterator lit = c.listIterator();while (lit.hasNext()){String s =(String)lit.next();if(s.equals("java")){lit.add("android"); // 在使用迭代器进行遍历的时候使用迭代器来进行修改}}System.out.println(c);}
}
foreach
foreach:增强for循环,一般用于遍历集合或者数组
格式:
for(元素的类型 变量 : 集合或者数组对象) {
可以直接使用变量;
}
注意:在增强for循环中不能修改集合,否则会出现并发修改异常,不能进行增减。
public interface Iterable
实现这个接口允许对象成为 "foreach" 语句的目标。
package com.demo04;import java.util.ArrayList;
import java.util.Collection;/** foreach:增强for循环,一般用于遍历集合或者数组* 格式:* for(元素的类型 变量 : 集合或者数组对象) {* 可以直接使用变量;* }注意:在增强for循环中不能修改集合,否则会出现并发修改异常,不能进行增减。public interface Iterable实现这个接口允许对象成为 "foreach" 语句的目标。*/
public class ForEachDemo {public static void main(String[] args) {/* //创建集合对象Collection c = new ArrayList();//添加元素c.add("hello");c.add("world");c.add("java");//增强for循环遍历集合for(Object obj : c) {System.out.println(obj);}for(String s : c) {s = s.toUpperCase()+"其他的内容";System.out.println(s);}for(String s : c) {System.out.println(s);}*/ /*for (String string : c) {c.add("android");System.out.println(string);}*/Collection<Student> c = new ArrayList<Student>();c.add(new Student("张三",20));c.add(new Student("李四",18));for(Student student:c) {System.out.println("name:"+student.name+" age:"+student.age);}/* for(Student student:c) { 用foreach对集合修改就出现异常 ConcurrentModificationException:并发修改异常System.out.println("name:"+student.name+" age:"+student.age);student.name = student.name+"xx";c.add(new Student("王五",22));}*/}}class Student {String name;int age;public Student(String name, int age) {super();this.name = name;this.age = age;}}
结果name:张三 age:20
name:李四 age:18
常见的数据结构
数组
数据结构图

特点:1.长度一旦定义就不能被改变;2.数组中的元素都有整数索引;3.数组只能存储同一数据类型的元素;4.数组既可以存储基本数据类型,也可以存储引用数据类型。
优点:检索快,因为可以通过索引获取数组元素
缺点:增加和删除数据慢,因为需要创建新的数据,效率低。
如何插入新的元素?如[1,2,3,4]3后面插入8。
首先创建一个新的数组,长度是原来的数组长度+1;接着遍历原来的数组并存储到新的数组中,遇到3的时候在它后面添加8,最后将剩下的元素添加到8后面即可。
链表
获取结点:

添加结点:

特点:由链子链接起来的一堆结点,有头结点和尾结点
优点:增加和删除元素快
缺点:查询慢,只能遍历列表一个个看

栈和队列

特点:栈:先进后出(子弹出夹);队列:先进先出。(买火车票进站)
优点:
缺点:
List
定义:List 组件为用户提供了一个可滚动的文本项列表。可设置此 list,使其允许用户进行单项或多项选择。
* List:* 有序的(存储和读取的顺序是一致的)* 有整数索引* 允许重复的** List的特有功能:* void add(int index, E element) 在列表的指定位置插入指定元素* E get(int index) 根据索引返回元素* E remove(int index) 删除指定元素并返回* E set(int index, E element) 将指定索引位置的元素替换为指定元素,并将原先的元素返回
package CollectionDemo;import java.util.ArrayList;
import java.util.List;/** List:* 有序的(存储和读取的顺序是一致的)* 有整数索引* 允许重复的** List的特有功能:* void add(int index, E element)* E get(int index)* E remove(int index) 删除指定元素并返回* E set(int index, E element)** 增删改查*/
public class ListDemo {public static void main(String[] args) {List list =new ArrayList();
// //void add(int index, E element) : 在列表的指定位置插入指定元素list.add(0,"hello");list.add(0,"c++");list.add(1,"java");System.out.println(list);
// E get(int index) :根据索引返回元素/*System.out.println(list.get(0));System.out.println(list.get(1));System.out.println(list.get(2));*/for (int i= 0;i<list.size();i++){System.out.println(list.get(i));}
// E remove(int index) : 删除指定元素并返回System.out.println(list.remove(1));System.out.println(list);
// 输出 [c++, hello]
// E set(int index, E element) : 将指定索引位置的元素替换为指定元素,并将原先的元素返回System.out.println(list.set(0,"and"));System.out.println(list);
// 输出 [and, hello]}
}
LinkedList

List的常用子类
ArrayList 底层是数组 增删慢,查询快
LinkedList 底层是链表 增删快,查询慢
如何选择使用不同的集合?
如果查询多,增删少,则使用ArrayList
如果查询少,增删多,则使用LinkedList
如果你不知道使用什么,则使用ArrayList
LinkedList的特有功能:
void addFirst(E e)
void addLast(E e)
E getFirst()
E getLast()
E removeFirst()
E removeLast()
package com.demo06;import java.util.LinkedList;*/
public class LinkedListDemo {public static void main(String[] args) {LinkedList<String> list = new LinkedList<String>();list.add("hello");list.add("world");//void addFirst(E e) :将元素添加到索引为0的位置//void addLast(E e) :将元素添加到索引为size()-1的位置//list.addFirst("java");//list.addLast("android");//E getFirst() :获取索引为0的元素//E getLast() :获取索引为size()-1的元素//System.out.println(list.getFirst());//System.out.println(list.getLast());System.out.println(list);//E removeFirst() :删除索引为0的元素并返回//E removeLast() :删除索引为size()-1的元素并返回//System.out.println(list.removeFirst());System.out.println(list.removeLast());System.out.println(list);}
}
package CollectionDemo;import java.util.LinkedList;/*
List的常用子类
ArrayList 底层是数组 增删慢,查询快
LinkedList 底层是链表 增删快,查询慢
如何选择使用不同的集合?如果查询多,增删少,则使用ArrayList如果查询少,增删多,则使用LinkedList如果你不知道使用什么,则使用ArrayListLinkedList的特有功能:void addFirst(E e)void addLast(E e)E getFirst()E getLast()E removeFirst()E removeLast()
*/
public class ListedListDemo {public static void main(String[] args) {LinkedList<String> list = new LinkedList<String>();list.add("hello");list.add("ho");list.addFirst("h");list.addLast("yy");System.out.println(list);
// 运行结果 [h, hello, ho, yy]System.out.println(list.getFirst()); //hSystem.out.println(list.getLast()); //yySystem.out.println(list.removeFirst()); // h删除索引为0的元素并返回System.out.println(list.removeLast()); //yySystem.out.println(list); //输出[hello, ho]}
}
案例 查找元素索引及判断元素是否存在案例
package com.demo07;import java.util.ArrayList;
import java.util.List;/** 需求:定义一个方法,返回指定列表中指定元素的索引位置* * 判断元素是否存在* */
public class ListTest {public static void main(String[] args) {List list = new ArrayList();list.add("hello");list.add("world");list.add("java");int index = index(list,"python");System.out.println(index);boolean flag = contains(list, "world");System.out.println(flag); //输出 1boolean flag1 = list.contains("java");System.out.println(flag1); // 输出true}public static int index(List list,Object other) {for(int x = 0;x < list.size();x++) {//获取列表中的元素Object obj = list.get(x);//使用列表中的元素和指定的元素进行比较if(obj.equals(other)) {return x;}}//查找不到指定的元素return -1;}public static boolean contains(List list,Object other) {//获取指定元素在指定列表中的索引位置int index = index(list,other);//如果索引位置大于等于0,则认为元素存在,否则不存在if(index >= 0) {return true;} else {return false;}}}
练习
1、
分析以下需求,并用代码实现
(1)生成10个1至100之间的随机整数(不能重复),存入一个List集合
(2)然后利用迭代器和增强for循环分别遍历集合元素并输出
(3)如:15 18 20 40 46 60 65 70 75 91
需求分析:
随机生成10个1至100之间的不重复整数,可以通过使用Java的Random类,生成随机数,再判断是否已经存在于集合中,如果存在则重新生成。
存储生成的随机数可以使用Java的List集合,因为它能够按照插入顺序存储元素。
遍历集合元素可以使用Java的迭代器和增强for循环。迭代器是遍历集合的标准方法,它能够对集合中的元素进行读取、删除和修改操作。增强for循环是一种简化版的迭代器,它可以遍历集合中的元素,但不能进行修改和删除操作。
输出集合元素可以使用Java的System.out.println方法,将每个元素输出到控制台。
import java.util.*;public class RandomNumbers {public static void main(String[] args) {List<Integer> numbers = new ArrayList<>();Random rand = new Random();// 生成10个1至100之间的不重复整数while (numbers.size() < 10) {int n = rand.nextInt(100) + 1;if (!numbers.contains(n)) {numbers.add(n);}}// 使用迭代器遍历集合并输出System.out.print("使用迭代器遍历集合:");Iterator<Integer> iterator = numbers.iterator();while (iterator.hasNext()) {int n = iterator.next();System.out.print(n + " ");}System.out.println();// 使用增强for循环遍历集合并输出System.out.print("使用增强for循环遍历集合:");for (int n : numbers) {System.out.print(n + " ");}System.out.println();}
}利用迭代器遍历集合并输出
63 82 15 69 9 87 52 92 93 40
利用for增强遍历集合并输出
63 82 15 69 9 87 52 92 93 40
2、
分析以下需求,并用代码实现
(1)定义List集合,存入多个字符串
(2)删除集合元素字符串中包含0-9数字的字符串(只要字符串中包含0-9中的任意一个数字就需要删除此整个字符串)
(3)然后利用迭代器遍历集合元素并输出
package CollectionDemo.Test;import java.util.*;
import java.util.List;
/*分析以下需求,并用代码实现(1)定义List集合,存入多个字符串(2)删除集合元素字符串中包含0-9数字的字符串(只要字符串中包含0-9中的任意一个数字就需要删除此整个字符串)(3)然后利用迭代器遍历集合元素并输出*/
public class Test2 {public static void main(String[] args) {
// 定义List集合,存入多个字符串List<String> list = new ArrayList<>();list.add("abc");list.add("efg");Iterator<String> iterator = list.iterator();while (iterator.hasNext()){String s = iterator.next();
// (2)删除集合元素字符串中包含0-9数字的字符串(只要字符串中包含0-9中的任意一个数字就需要删除此整个字符串)if (s.matches(".*[0-9].*")){iterator.remove();}}
// (3)然后利用迭代器遍历集合元素并输出for (String s:list) {System.out.println(s);}}
}
abc
efg
分析以下需求,并用代码实现
(1)定义Person类包含姓名:String name、年龄:int age、成绩:int score,生成空参、有参构造、set和get方法、toString方法
(2)定义Student类继承Person,属性与Person类相同
(3)查看API中ArrayList集合中的以下方法:
(a)boolean add(E e) 方法
(b) T[] toArray(T[] a)方法
(c)boolean addAll(Collection extends E> c)方法
(4)通过查看API对以上方法的学习,完成以下功能
a. ArrayList集合中存入5个Student对象,将ArrayList集合转成对应的数组Studentp[],并遍历打印数组中的元素
b. 定义一个存储Person对象的ArrayList集合对象list1,并出入2个Person对象,定义一个存储Student对象的ArrayList集合对象list2,并出入2个Student对象,
调用addAll方法将list2的全部内容添加到list1中,遍历打印list1中的内容
package CollectionDemo.Test;import java.util.ArrayList;/*分析以下需求,并用代码实现(1)定义Person类包含姓名:String name、年龄:int age、成绩:int score,生成空参、有参构造、set和get方法、toString方法(2)定义Student类继承Person,属性与Person类相同(3)查看API中ArrayList集合中的以下方法:(a)boolean add(E e) 方法(b) T[] toArray(T[] a)方法(c)boolean addAll(Collection extends E> c)方法(4)通过查看API对以上方法的学习,完成以下功能a. ArrayList集合中存入5个Student对象,将ArrayList集合转成对应的数组Studentp[],并遍历打印数组中的元素b. 定义一个存储Person对象的ArrayList集合对象list1,并出入2个Person对象,定义一个存储Student对象的ArrayList集合对象list2,并出入2个Student对象,调用addAll方法将list2的全部内容添加到list1中,遍历打印list1中的内容*/
public class Test3 {public static void main(String[] args) {// a. ArrayList集合中存入5个Student对象,将ArrayList集合转成对应的数组Studentp[],并遍历打印数组中的元素ArrayList<Person.Student> arrayList = new ArrayList<Person.Student>();arrayList.add(new Person.Student("小结",16,79));arrayList.add(new Person.Student("小结2",13,45));//b. 定义一个存储Person对象的ArrayList集合对象list1,并出入2个Person对象,定义一个存储Student对象的ArrayList集合对象 Person.Student[] stu = arrayList.toArray(new Person.Student[arrayList.size()]);for (Person.Student st:stu) {System.out.println(st);}}
}
//(1)定义Person类包含姓名:String name、年龄:int age、成绩:int score,生成空参、有参构造、set和get方法、toString方法
class Person{String name;int age;int score;
// 空参构造public Person() {}// 有参构造public Person(String name, int age, int score) {this.name = name;this.age = age;this.score = score;}
//set和get方法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;}public int getScore() {return score;}public void setScore(int score) {this.score = score;}public String toString(){return "Person{"+"name="+name+'\''+",age="+age+",score="+score+"}";}// (2)定义Student类继承Person,属性与Person类相同static class Student extends Person{public Student(String name, int age, int score) {super(name, age, score);}
}
}
4.现在已知Cloth ,衣物都有颜色,价格,牌子;
已知裤子是衣物的一种,裤子有裤袋;
已知袜子也是一种,袜子有个洞;
已知衬衣也是衣服的一种,衬衣有扣子;
已知鞋子也是衣物,鞋子有鞋带
已知人这个类, 人类有姓名,性别, 可以穿衣服;
要求: 定义一个衣柜(衣柜不用创建对象, 里面放置一套衣服);
创建人对象,然后实现穿一套衣服的过程;
package CollectionDemo.Test;
/*现在已知Cloth ,衣物都有颜色,价格,牌子;已知裤子是衣物的一种,裤子有裤袋;已知袜子也是一种,袜子有个洞;已知衬衣也是衣服的一种,衬衣有扣子;已知鞋子也是衣物,鞋子有鞋带已知人这个类, 人类有姓名,性别, 可以穿衣服;要求: 定义一个衣柜(衣柜不用创建对象, 里面放置一套衣服);创建人对象,然后实现穿一套衣服的过程;*/
public class Test4 {public static void main(String[] args) {Person1 person1 = new Person1();person1.name="Mary";person1.gender = "female";Wardrobe wardrobe = new Wardrobe();person1.wear(wardrobe.pants);person1.wear(wardrobe.socks);person1.wear(wardrobe.shirt);person1.wear(wardrobe.shoes);}
}
class Cloth{String color;double price;String brand;
}
class Pants extends Cloth{boolean hasPocket; //有口袋
}
class Socks extends Cloth{boolean hasHole;
}
class Shirt extends Cloth{boolean hasButton;
}
class Shoes extends Cloth{boolean hasLaces;
}
class Person1 {String name;String gender;void wear(Cloth cloth) {System.out.println(name + " is wearing " + cloth.brand + " " + cloth.getClass().getSimpleName() + ".");}
}
class Wardrobe{Pants pants = new Pants();Socks socks = new Socks();Shirt shirt =new Shirt();Shoes shoes = new Shoes();Wardrobe(){pants.color="blue";pants.price=36.88;pants.brand="LOV";pants.hasPocket=true;socks.color = "white";socks.price = 4.99;socks.brand = "Hanes";socks.hasHole = true;shirt.color = "pink";shirt.price = 39.99;shirt.brand = "Ralph Lauren";shirt.hasButton = true;shoes.color = "black";shoes.price = 79.99;shoes.brand = "Nike";shoes.hasLaces = true;}
}
Mary is wearing LOV Pants.
Mary is wearing Hanes Socks.
Mary is wearing Ralph Lauren Shirt.
Mary is wearing Nike Shoes.
键盘录入若干个字符串,将字符串存入泛型为String的集合当中, 知道输入quit的时候不用输入;
1.集合中含有字符a的元素有多少个
2.将集合中第三个元素中"a"全部替换成"b";
3.删掉长度为3的元素;
4.遍历集合;
package CollectionDemo.Test;import java.util.ArrayList;
import java.util.Iterator;
import java.util.Scanner;/*键盘录入若干个字符串,将字符串存入泛型为String的集合当中, 直到输入quit的时候不用输入;1.集合中含有字符a的元素有多少个2.将集合中第三个元素中"a"全部替换成"b";3.删掉长度为3的元素;4.遍历集合;*/
public class Test5 {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);ArrayList<String> stringList = new ArrayList<>(); // 创建泛型为String的ArrayListSystem.out.println("请输入字符串(输入quit结束输入):");// 用循环读取用户输入的字符串并存入ArrayList,直到输入"quit"为止while (true) {String input = scanner.nextLine();if (input.equals("quit")) {break;} else {stringList.add(input);}}// 打印集合中含有字符a的元素数量int count = 0;for (String str : stringList) {if (str.contains("a")) {count++;}}System.out.println("集合中含有字符a的元素数量为:" + count);// 将集合中第三个元素中"a"全部替换成"b"if (stringList.size() >= 3) { // 确保集合中至少有3个元素String thirdElement = stringList.get(2);stringList.set(2, thirdElement.replace("a", "b"));}// 删除长度为3的元素stringList.removeIf(str -> str.length() == 3);// 遍历集合并打印每个元素System.out.println("遍历集合:");for (String str : stringList) {System.out.println(str);}}
}请输入字符串(输入quit结束输入):
sdha
jkhg
ghsa
quit
集合中含有字符a的元素数量为:2
遍历集合:
sdha
jkhg
ghsb
第十八章 Set与Map集合
Set
- 定义
在Java中,Set是一种集合类型,它继承自Collection接口,用于存储不重复的元素。Set接口的定义如下:
public interface Set<E> extends Collection<E> {// 声明Set特有的方法
}
常用的Set实现类有HashSet、TreeSet和LinkedHashSet。
需要注意的是,Set接口是一个抽象接口,不能直接实例化。需要使用Set接口的实现类来创建Set对象。
- 特点
- 无序
- 不重复
- 没有整数索引

- 方法
add() toArray()

增强for循环
增强for循环语法(也称为for-each循环)是Java中用于遍历数组或集合的简化循环语法。其语法形式如下:
for (elementType element : collection) {// 循环体
}
其中:
elementType 是集合中元素的类型,也可以是数组的元素类型。
element 是循环变量,用于在每次循环迭代中代表集合中的一个元素。
collection 是要遍历的集合或数组。
增强for循环的工作原理是自动迭代集合或数组,并将每个元素依次赋值给循环变量,然后执行循环体中的代码。循环将在集合或数组中的每个元素上执行一次,直到所有元素都被遍历完为止。
需要注意的是,增强for循环只能用于遍历集合或数组,无法用于遍历其他数据结构或自定义对象。
使用HashSet存储字符串并遍历
package mySet;import java.util.HashSet;
import java.util.Set;/*使用HashSet存储字符串并遍历** Set的特点:* 无序(存储和读取的顺序可能不一样)* 不允许重复* 没有整数索引*/
public class hashSetDemo1 {public static void main(String[] args) {
// 创建集合Set<String> set = new HashSet<>(); //必须要是泛型的
// 添加元素set.add("hello");set.add("world");set.add(null);System.out.println(set.add("java"));System.out.println(set.add("java")); //不允许有重复的元素,所以值输出一个java
// 遍历元素for(String s : set){System.out.println(s);}}
}
输出
true
false
null
world
java
hello
为啥输出了true和false?
这段代码输出了"true"和"false",以及集合中的元素。
首先,让我们逐行分析代码的执行:
创建HashSet对象并将其赋值给set变量:Set set = new HashSet<>();
创建一个名为set的HashSet集合,其中存储的元素类型为String。
添加元素到集合中:
set.add(“hello”);:向集合中添加字符串"hello"。
set.add(“world”);:向集合中添加字符串"world"。
set.add(null);:向集合中添加一个null元素。
System.out.println(set.add(“java”));:向集合中添加字符串"java",并输出add方法的返回值。因为集合中原本没有"java"这个元素,所以添加成功,返回true,因此输出为"true"。
System.out.println(set.add(“java”));:再次向集合中添加字符串"java",并输出add方法的返回值。因为集合中已经存在"java"这个元素,添加失败,返回false,因此输出为"false"。
遍历集合中的元素:
使用增强for循环遍历集合中的元素。
for(String s : set){…}:对于集合中的每个元素,将其赋值给变量s,并执行循环体中的代码。
循环体中的代码System.out.println(s);将每个元素打印到控制台。
hashSet
-
定义
HashSet实现了Set接口,并且还继承了AbstractSet类,同时也实现了Cloneable接口和Serializable接口。它使用哈希表来存储元素,并且允许存储null元素(只能存储一个)。

-
特点
- 不允许重复元素:HashSet中不会包含重复的元素。当向HashSet中添加元素时,会先通过元素的hashCode()方法计算哈希值,然后根据哈希值确定元素在内部存储结构中的位置。如果发现该位置已经存在元素,则进行比较,如果元素已经存在,则不会添加;如果元素不存在,则将其添加到该位置。
- 无序性:HashSet中的元素没有特定的顺序。HashSet不会保持元素的插入顺序,也不会按照元素的排序顺序存储。
- 高效的查找和插入操作:HashSet基于哈希表实现,因此查找和插入操作的性能非常高效,具有常数时间复杂度O(1)。
可以存储null元素:HashSet可以存储一个null元素,但不能存储多个null元素,因为HashSet要求元素唯一。 - 不是线程安全的:HashSet不是线程安全的,如果多个线程同时访问一个HashSet并且至少有一个线程修改了集合,则必须进行外部同步。
遍历性能较好:由于HashSet使用哈希表实现,遍历HashSet的性能较好。
注意:由于HashSet使用哈希表实现,元素的顺序是根据哈希值决定的,因此无法保证HashSet的元素顺序是固定的。如果需要有序的集合,可以使用LinkedHashSet类,它在HashSet的基础上使用了链表来维护元素的插入顺序。
-
add()
HashSet的add()方法,首先会使用当前集合中的每一个元素和新添加的元素进行hash值比较,
如果hash值不一样,则直接添加新的元素
如果hash值一样,比较地址值或者使用equals方法进行比较
比较结果一样,则认为是重复不添加
所有的比较结果都不一样则添加 -
方法

方法重载与重写
方法重写与方法重载区别
方法重写@override 在子类当中,子类和父类的方法完全一样,子类覆盖了父类的方法,重写之后,使用子类对象调用的就是子类的方法。
方法重载@overload 在一个类中有多个重名方法,但是方法参数不同(参数类型、数目,顺序),和返回值无关。
使用HashSet存储自定义对象并遍历
package mySet;import java.util.HashSet;/** 使用HashSet存储自定义对象并遍历** HashSet的add()方法,首先会使用当前集合中的每一个元素和新添加的元素进行hash值比较,* 如果hash值不一样,则直接添加新的元素* 如果hash值一样,比较地址值或者使用equals方法进行比较* 比较结果一样,则认为是重复不添加* 所有的比较结果都不一样则添加*/
public class hashSetDemo2 {public static void main(String[] args) {
// 创建集合对象HashSet<Student> hashSet = new HashSet<Student>();
// 创建元素对象Student s = new Student("张三",18);Student s2 = new Student("lisi",18);Student s3 = new Student("lisi",18);
// 添加元素hashSet.add(s);hashSet.add(s2);hashSet.add(s3);
// 遍历集合对象 自定义的类for (Student student:hashSet) {System.out.println(student);}}
}class Student {String name;int age;public Student(String name,int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Student [name=" + name + ", age=" + age + "]";}@Overridepublic boolean equals(Object obj) {System.out.println("-------------------");Student s = (Student)obj;//向下转型,可以获取子类特有成员//比较年龄是否相等,如果不等则返回falseif(this.age != s.age) {return false;}//比较姓名是否相等,如果不等则返回falseif(!this.name.equals(s.name)) {return false;}//默认返回true,说明两个学生是相等的return true;}@Overridepublic int hashCode() {return 1;}
}
hashCode方法和equals方法的优化
我们发现当hashCode方法永远返回整数1时,所有对象的hash值都是一样的, 有一些对象的成员变量完全不同,但是它们还需要进行hash和equals方法的比较,如果我们可以让成员变量不同的对象,它们的hash值也不同,这就可以减少一部分equals方法的比较从而可以提高我们程序的效率
可以尝试着让hashCode方法的返回值和对象的成员变量有关可以让hashCode方法返回所有成员变量之和,让基本数据类型直接相加,然后引用数据类型获取hashCode方法返回值后再相加(boolean不可以参与运算)
package mySet;import java.util.HashSet;public class HashSetDemo3 {public static void main(String[] args) {//创建集合对象HashSet<Person> hs = new HashSet<Person>();//创建元素对象Person p = new Person("zhangsan",18);Person p2 = new Person("lisi",21);Person p3 = new Person("lisi",20);//添加元素对象hs.add(p);hs.add(p2);hs.add(p3);//遍历集合对象for (Person person : hs) {System.out.println(person);}}
}
Person.java
package com.demo02;public class Person {String name;int age;public Person(String name,int age) {this.name = name;this.age = age;}
//自动生成的方法重写@Overridepublic String toString() {return "Person [name=" + name + ", age=" + age + "]";}@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + age;result = prime * result + ((name == null) ? 0 : name.hashCode());return result;}@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj == null)return false;if (getClass() != obj.getClass())return false;Person other = (Person) 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;}/* 自己写的@Overridepublic int hashCode() { //return age;return age + name.hashCode();}@Overridepublic boolean equals(Object obj) {System.out.println("-------------");//提高效率if(this == obj) {return true;}//提高健壮性if(this.getClass() != obj.getClass()) {return false;}//向下转型Person p = (Person)obj;if(!this.name.equals(p.name)) {return false;}if(this.age != p.age) {return false;}return true;}*/}
Collection
定义
Collection 层次结构 中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。JDK 不提供此接口的任何直接 实现:它提供更具体的子接口(如 Set 和 List)实现。此接口通常用来传递 collection,并在需要最大普遍性的地方操作这些 collection。
Collections:
Collection和Collections有什么区别?
面试题:Collection和Collections有什么区别?
Collection是集合体系的最顶层,包含了集合体系的共性
Collections是一个工具类,方法都是用于操作Collection

- Collection

collection方法

- static void swap(List list, int i, int j) :将指定列表中的两个索引进行位置互换
- static int binarySearch(List list, Object key) 使用二分查找法查找指定元素在指定列表的索引位置 1 2 3 4 5 6 7
- static void copy(List dest, List src) :是把源列表中的数据覆盖到目标列表
注意:目标列表的长度至少等于源列表的长度 - static void fill(List list, Object obj) :使用指定的对象填充指定列表的所有元素
- static void reverse(List list) :反转
- static void sort(List list) :按照列表中元素的自然顺序进行排序
public class CollectionsDemo {public static void main(String[] args) {method7();}private static void method7() {//static void swap(List list, int i, int j) :将指定列表中的两个索引进行位置互换List<Integer> list = new ArrayList<Integer>();list.add(1);list.add(2);list.add(3);list.add(4);list.add(7);list.add(0);list.add(-1);System.out.println(list);Collections.swap(list, 2, 5);System.out.println(list);}private static void method() {//static int binarySearch(List list, Object key) 使用二分查找法查找指定元素在指定列表的索引位置 1 2 3 4 5 6 7List<Integer> list = new ArrayList<Integer>();list.add(1);list.add(2);list.add(3);list.add(4);list.add(5);list.add(6);list.add(7);int index = Collections.binarySearch(list, 4);System.out.println(index);}private static void method2() {//static void copy(List dest, List src) :是把源列表中的数据覆盖到目标列表//注意:目标列表的长度至少等于源列表的长度//创建源列表List<String> src = new ArrayList<String>();src.add("hello");src.add("world");src.add("java");//创建目标列表List<String> dest = new ArrayList<String>();dest.add("java");dest.add("java");//dest.add("java");//dest.add("java");Collections.copy(dest, src);System.out.println(dest);}private static void method3() {//static void fill(List list, Object obj) :使用指定的对象填充指定列表的所有元素List<String> list = new ArrayList<String>();list.add("hello");list.add("world");list.add("java");System.out.println(list);Collections.fill(list, "android");System.out.println(list);}private static void method4() {//static void reverse(List list) :反转List<Integer> list = new ArrayList<Integer>();list.add(1);list.add(2);list.add(3);list.add(4);System.out.println(list);Collections.reverse(list);System.out.println(list);}private static void method5() {//static void shuffle(List list):傻否,随机置换 List<Integer> list = new ArrayList<Integer>();list.add(1);list.add(2);list.add(3);list.add(4);System.out.println(list);Collections.shuffle(list);System.out.println(list);}private static void method6() {//static void sort(List list) :按照列表中元素的自然顺序进行排序 List<Integer> list = new ArrayList<Integer>();list.add(1);list.add(4);list.add(3);list.add(2);System.out.println(list);Collections.sort(list);System.out.println(list);}
}
输出:
[1, 2, 3, 4, 7, 0, -1]
[1, 2, 0, 4, 7, 3, -1]
Collection练习 模拟斗地主
package com.demo03;import java.util.ArrayList;
import java.util.Collections;/** 模拟斗地主发牌 买牌洗牌发牌*/
public class CollectionsTest {public static void main(String[] args) {//String[] box0 = {"黑桃A","黑桃2"...}//买牌String[] arr = { "黑桃", "红桃", "方片", "梅花" };String[] arr2 = { "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K" };ArrayList<String> box = new ArrayList<String>();//添加每张牌for (int i = 0; i < arr.length; i++) {//获取每一个花色for (int j = 0; j < arr2.length; j++) {//获取每一个数box.add(arr[i] + arr2[j]);}}box.add("大王");box.add("小王");System.out.println(box.size());System.out.println(box);//洗牌Collections.shuffle(box);System.out.println(box);//发牌ArrayList<String> 林志玲 = new ArrayList<String>();ArrayList<String> 林心如 = new ArrayList<String>();ArrayList<String> 舒淇 = new ArrayList<String>();//留三张底牌给地主for (int i = 0; i < box.size() - 3; i++) {/* i = 0;i % 3 = 0;i = 1;i % 3 = 1;i = 2;i % 3 = 2;i = 3;i % 3 = 0;i = 4;i % 4 = 1;i = 5;i % 5 = 2;*/if(i % 3 == 0) {林志玲.add(box.get(i));}else if(i % 3 == 1) {林心如.add(box.get(i));}else if(i % 3 == 2) {舒淇.add(box.get(i));}}System.out.println("林志玲:" + 林志玲);System.out.println("林心如:" + 林心如);System.out.println("舒淇:" + 舒淇);System.out.println("底牌:");/*System.out.println(box.get(box.size() - 1));System.out.println(box.get(box.size() - 2));System.out.println(box.get(box.size() - 3));*/for (int i = box.size() - 3; i < box.size(); i++) {System.out.println(box.get(i));}}}
54
[黑桃A, 黑桃2, 黑桃3, 黑桃4, 黑桃5, 黑桃6, 黑桃7, 黑桃8, 黑桃9, 黑桃10, 黑桃J, 黑桃Q, 黑桃K, 方块A, 方块2, 方块3, 方块4, 方块5, 方块6, 方块7, 方块8, 方块9, 方块10, 方块J, 方块Q, 方块K, 红桃A, 红桃2, 红桃3, 红桃4, 红桃5, 红桃6, 红桃7, 红桃8, 红桃9, 红桃10, 红桃J, 红桃Q, 红桃K, 梅花A, 梅花2, 梅花3, 梅花4, 梅花5, 梅花6, 梅花7, 梅花8, 梅花9, 梅花10, 梅花J, 梅花Q, 梅花K, 大王, 小王]
[红桃7, 梅花J, 梅花4, 黑桃4, 大王, 方块2, 梅花2, 黑桃6, 方块7, 方块3, 方块Q, 黑桃A, 黑桃3, 梅花8, 红桃8, 红桃10, 梅花10, 黑桃10, 红桃A, 红桃K, 黑桃9, 方块A, 梅花Q, 梅花5, 红桃6, 黑桃7, 梅花A, 红桃5, 红桃4, 红桃2, 方块4, 方块10, 方块8, 方块K, 黑桃5, 方块6, 方块J, 红桃Q, 梅花6, 红桃J, 黑桃J, 红桃3, 方块9, 梅花7, 方块5, 黑桃K, 梅花K, 红桃9, 小王, 黑桃Q, 黑桃8, 黑桃2, 梅花9, 梅花3]
林志玲[红桃7, 黑桃4, 梅花2, 方块3, 黑桃3, 红桃10, 红桃A, 方块A, 红桃6, 红桃5, 方块4, 方块K, 方块J, 红桃J, 方块9, 黑桃K, 小王]
林心如[梅花J, 大王, 黑桃6, 方块Q, 梅花8, 梅花10, 红桃K, 梅花Q, 黑桃7, 红桃4, 方块10, 黑桃5, 红桃Q, 黑桃J, 梅花7, 梅花K, 黑桃Q]
舒淇[梅花4, 方块2, 方块7, 黑桃A, 红桃8, 黑桃10, 黑桃9, 梅花5, 梅花A, 红桃2, 方块8, 方块6, 梅花6, 红桃3, 方块5, 红桃9, 黑桃8]
底牌:
黑桃2
梅花9
梅花3
Map
需求:实现学号和姓名这样有对应关系的数据存储
- 为了体现这种有对应关系的数据,我们使用以前所学的内容是可以实现的,但是略有不便,所以java又给我们提供了一种专门用于存储对应关系的集合。
Map:将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值
Map和Collection有什么区别?
Map:是一个双列集合,常用语处理有对应关系的数据,key是不可以重复的,我们也称之为是夫妻对集合
Collection:是单列集合,Collection有不同的子体系,有的允许重复有索引有序,有的不允许重复而且无序,那么我们也称之为单身汉集合
一对一:一个学号对应一个姓名。
定义:将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。
map常用功能
映射功能:
V put(K key, V value)
获取功能:
V get(Object key)
int size()
判断功能:
boolean containsKey(Object key)
boolean containsValue(Object value)
boolean isEmpty()
删除功能:
void clear()
V remove(Object key)
遍历功能:
Set
-
SetkeySet() -
Collectionvalues()
public class MapDemo2 {public static void main(String[] args) {//创建Map对象Map<String,String> map = new HashMap<String,String>();//V put(K key, V value) :就是将key映射到value,如果key存在,则覆盖value,并将原来的value返回System.out.println(map);System.out.println(map.put("s001", "张三"));System.out.println(map.put("s002", "李四"));System.out.println(map.put("s001", "王五"));//System.out.println(map.put("s001", null));System.out.println(map);//V get(Object key) : 根据指定的key返回对应的value//System.out.println(map.get("s002"));//System.out.println(map.get("s002sdf"));//int size() : 返回对应关系的个数//System.out.println(map.size());//boolean containsKey(Object key) : 判断指定key是否存在//System.out.println(map.containsKey("s003"));//System.out.println(map.containsKey("s002"));//boolean containsValue(Object value):判断指定的value是否存在//System.out.println(map.containsValue("王五"));//System.out.println(map.containsValue("王"));//void clear() : 清空所有的对应关系 //map.clear();//System.out.println(map);//V remove(Object key) :根据指定的key删除对应关系,并返回key所对应的值,如果没有删除成功则返回nullSystem.out.println(map.remove("s005"));System.out.println(map.remove("s002"));System.out.println(map);//boolean isEmpty() : 判断是否有对应关系System.out.println(map.isEmpty());map.clear();System.out.println(map);System.out.println(map.isEmpty());}
}
Set keySet() 获取map的键,Collection values() 获取map的值
/** Set keySet() * Collection values() */
public class MapDemo3 {public static void main(String[] args) {//创建Map对象Map<String,String> map = new HashMap<String,String>();//添加映射关系map.put("s001", "张三");map.put("s002", "李四");map.put("s005", "李四");//Set keySet() : 以Set的形式获返回所有的key Set<String> keys = map.keySet();for (String key : keys) {System.out.println(key);}System.out.println("-----------");//Collection values() : Collection<String> values = map.values();for (String value : values) {System.out.println(value);}}
}s005
s002
s001
-----------
李四
李四
张三
map的两种遍历方式
- map的第一种遍历方式
首先召集所有的键(丈夫):
Set<String> keys = map.keySet();
遍历所有的键(丈夫):
for (String key : keys) {//让每个丈夫去找他自己的媳妇就可以了String value = map.get(key);System.out.println("丈夫:" + key + "---" + "媳妇:" + value);
}
获取每一个键(丈夫)
让每一个键(丈夫)去找他自己的值(媳妇)
/** Map的第一种遍历方式:* 首先召集所有的丈夫* 遍历所有的丈夫* 获取每一个丈夫* 让每一个丈夫去找他自己的媳妇*/
public class MapDemo4 {public static void main(String[] args) {//创建Map对象Map<String,String> map = new HashMap<String,String>();//添加映射关系map.put("谢婷疯", "张箔纸");map.put("陈关西", "钟欣桶");map.put("李亚碰", "王飞");//遍历Map对象//首先召集所有的丈夫Set<String> keys = map.keySet();//遍历所有的丈夫for (String key : keys) {//让每个丈夫去找他自己的媳妇就可以了String value = map.get(key);System.out.println("丈夫:" + key + "---" + "媳妇:" + value);}}
}
Map的第二种遍历方式
通过结婚证对象来获取丈夫和媳妇
for (Map.Entry<String, String> entry : entrys) {//获取每个单独的结婚证对象//通过结婚证对象获取丈夫和媳妇String key = entry.getKey();String value = entry.getValue(); System.out.println("丈夫:" + key + "---" + "媳妇:" + value);}
Set<Map.Entry<K,V>> entrySet()
/** Map的第二种遍历方式:* 通过结婚证对象来获取丈夫和媳妇* Set> entrySet() * */
public class MapDemo5 {public static void main(String[] args) {//创建Map对象Map<String,String> map = new HashMap<String,String>();//添加映射关系map.put("尹志平", "小龙女");map.put("令狐冲", "东方姑娘");map.put("玄慈", "叶二娘");//获取所有的结婚证对象Set<Map.Entry<String,String>> entrys = map.entrySet();//遍历包含了结婚证对象的集合for (Map.Entry<String, String> entry : entrys) {//获取每个单独的结婚证对象//通过结婚证对象获取丈夫和媳妇String key = entry.getKey();String value = entry.getValue();System.out.println("丈夫:" + key + "---" + "媳妇:" + value);}}
}
使用HashMap存储数据并遍历(字符串作为key)
package com.demo02;import java.util.HashMap;
import java.util.Map;
import java.util.Set;/** * 使用HashMap存储数据并遍历(字符串作为key)* */
public class HashMapDemo {public static void main(String[] args) {//创建Map对象HashMap<String,String> hm = new HashMap<String,String>();//添加映射关系hm.put("s001", "张三");hm.put("s002", "李四");hm.put("s003", "王五");hm.put("s003", "赵六");//遍历Map对象//方式1 获取所有的key,通过key来获取valueSet<String> keys = hm.keySet();for (String key : keys) {String value = hm.get(key);System.out.println(key + "=" + value);}System.out.println("------------------");//方式2:获取所有的结婚证对象,然后通过结婚证对象获取丈夫和媳妇Set<Map.Entry<String, String>> entrys = hm.entrySet();for (Map.Entry<String, String> entry : entrys) {String key = entry.getKey();String value = entry.getValue();System.out.println(key + "=" + value);}}
}
使用HashMap存储数据并遍历(自定义对象作为key)
package com.demo02;import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;/** * 使用HashMap存储数据并遍历(自定义对象作为key)* */
public class HashMapDemo2 {public static void main(String[] args) {//创建Map对象HashMap<Student,String> hm = new HashMap<Student,String>();//创建key对象Student s = new Student("zhangsan",18);Student s2 = new Student("lisi",20);Student s3 = new Student("lisi",20);//添加映射关系hm.put(s, "s001");hm.put(s2, "s002");hm.put(s3, "s002");//遍历Map对象//方式1: 获取所有的key,通过key来获取valueSet<Student> keys = hm.keySet();for (Student key : keys) {String value = hm.get(key);System.out.println(key + "=" + value);}System.out.println("-----");//方式2:获取所有结婚证对象,通过结婚证对象获取丈夫和媳妇Set<Map.Entry<Student, String>> entrys = hm.entrySet();for (Entry<Student, String> entry : entrys) {Student key = entry.getKey();String value = entry.getValue();System.out.println(key + "=" + value);}}
}
Student类
package com.demo02;public class Student {String name;int age;public Student(String name,int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Student [name=" + name + ", age=" + age + "]";}@Overridepublic int hashCode() {final int prime = 31;int result = 1;result = prime * result + age;result = prime * result + ((name == null) ? 0 : name.hashCode());return result;}@Overridepublic 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;}
}
异常的处理
异常的概述和体系结构.
-
Exception in thread “main” java.lang.ArithmeticException: / by zero
at com.demo01.ExceptionDemo.main(ExceptionDemo.java:5)
我们在写代码的时候,经常的出现一些小问题,那么为了方便我们处理这些问题,java为我们提供了异常机制
异常包含了错误的类型、原因以及位置异常:不正常,我们在代码的时候出现的编译或者运行时的错误
异常的体系结构: font>
Throwable(最顶层)
Error:出现的不能够处理的严重问题
Exception:可以处理的问题电脑坏了:
系统中毒:重装系统就可以了 这是Exception
主板坏了:买一台新的 这是Error
什么是异常?举例子:
public class exceptionDemo {public static void main(String[] args) {int a = 10 / 0;System.out.println(a);}
}
输出:出现异常
Exception in thread “main” java.lang.ArithmeticException: / by zero
at ExceptionDemo.exceptionDemo.main(exceptionDemo.java:5)

Throwable

JVM处理异常的方式
1.捕获处理
try…catch语句
try…catch的执行顺序:
首先执行try语句如果发现异常,异常下面的代码不再执行,直接跳入catch语句中,catch语句结束后,整个try…catch结束
如果没有发现异常,try语句执行结束后,try…catch直接结束, 不再执行catch语句
try{有可能出现问题的代码;}catch(ArithmeticException ae){处理异常;}
2.抛出去
当我们不想处理异常,或者没有能力处理的时候,我们可以选择抛出异常,谁调用方法谁处理异常
使用关键字throws在方法的声明出抛出异常
jvm处理异常的方式:
如果出现异常我们没有处理,jvm会帮我们进行处理,它会把异常的类型,原因还有位置显示在命令行,并且还终止了程序,异常后面的代码将不在执行。
public class ExceptionDemo2 {public static void main(String[] args) throws Exception {/*try {System.out.println("执行前");int a = 10 / 2;System.out.println("执行后");System.out.println(a);}catch(ArithmeticException e) {System.out.println("不能除0");}System.out.println("执行完问题语句后");*/try {readFile();}catch(FileNotFoundException e) {System.out.println("没有发现文件");}}public static void readFile() throws FileNotFoundException {FileReader fr = new FileReader("d:\\a.txt");}
}
如何处理多个异常
可以使用多个try…catch语句
使用一个try和多个catch
多个catch之间的顺序:
多个catch之间可以有子父类
平级之间没有顺序关系
如果有子父类,父类异常必须放在后面
public class ExceptionDemo3 {public static void main(String[] args) {try {String s = "1";System.out.println(s.length());int[] arr = new int[5];System.out.println(arr[4]);int i = 10;System.out.println(i/0);} catch (ArrayIndexOutOfBoundsException e) {System.out.println("数组越界异常");} catch (NullPointerException e) {System.out.println("空指针异常");} catch (Exception e) {System.out.println("异常");}}}
Throwable的常用方法
Throwable的常用方法:
- String getMessage() 原因
- String toString() 类型和原因
- void printStackTrace() 类型原因和位置
public class exceptionDemo2 {public static void main(String[] args) {try{System.out.println(2 / 0);}catch (ArithmeticException e){
// String getMessage():原因System.out.println(e.getMessage());
// String toString()类型和原因System.out.println(e.toString());
// void printStackTrace():类型原因和位置e.printStackTrace();}}
}

finally概述和应用场景
finally:组合try…catch使用,用于释放资源等收尾工作,无论try…catch语句如何执行,finally的代码一定会执行。
try{有可能出现问题的代码;
}catch(异常对象){处理异常;
}finally{释放资源;清理垃圾;
}
package ExceptionDemo;import java.io.FileWriter;
import java.io.IOException;public class finallyDemo {public static void main(String[] args) {FileWriter fileWriter = null;try{fileWriter = new FileWriter("a.txt");fileWriter.write("你好");System.out.println(2/0);fileWriter.write("我在学java");} catch (IOException e) {e.printStackTrace();}finally {try{fileWriter.close();}catch (IOException e){e.printStackTrace();}}}
}
输出:Exception in thread “main” java.lang.ArithmeticException: / by zero
at ExceptionDemo.finallyDemo.main(finallyDemo.java:12)
异常的分类
异常的分类:
运行时期异常:RuntimeException的子类就是运行时期异常,在编译时期可以自由选择处理或者不处理。RuntimeException 是那些可能在 Java 虚拟机正常运行期间抛出的异常的超类。例如:ArithmeticException(当出现异常的运算条件时,抛出此异常。例如,一个整数“除以零”时,抛出此类的一个实例。 )
编译时期异常:是Exception的子类,非RuntimeExcpetion的子类,在编译时期必须处理

举例子:
public class exceptionClassification {public static void main(String[] args) throws IOException {/* System.out.println(2 / 0);String s = null;System.out.println(s.length());运行时异常 输出 ArithmeticException*/FileWriter fw = new FileWriter("a.txt"); //编译异常,在编译的时候必须处理,处理方式就是抛出异常}
}
自定义异常
自定义异常的方法:写一个类去继承Exception或者RuntimeException,然后实现多个构造即可
1.先自定义异常:写一个类去继承Exception或者RuntimeException
package ExceptionDemo;public class MyException extends RuntimeException{private static final long serialVersionUID = 1L;public MyException(){super();}public MyException(String s){super(s);System.out.println("自定义异常");}
}
2.实现多个构造
package ExceptionDemo;public class exceptionDemo3 {public static void main(String[] args) {checkScore(110);}public static void checkScore(int score) throws MyException{if(score < 0 || score > 0){throw new MyException("考试不符合要求");}System.out.println("符合要求");}
}
输出:
自定义异常
Exception in thread “main” ExceptionDemo.MyException: 考试不符合要求
at ExceptionDemo.exceptionDemo3.checkScore(exceptionDemo3.java:9)
at ExceptionDemo.exceptionDemo3.main(exceptionDemo3.java:5)
递归概述和例题
递归:把大问题拆成很多小问题,然后再把小问题拆成更多的小问题,
当我们把更多小问题解决了,小问题也解决了
随着小问题的解决,大问题也随之解决了
在方法本身不断的调用方法自己
递归注意事项:==递归一定要有出口,内存溢出====递归次数不宜过多,内存溢出==
package Recurrence;
/** 需求:求5的阶乘* 5! = 5 * 4 * 3 * 2 * 1; //120* 5! = 5 * 4!; //120* 4! = 4 * 3!; //24* 3! = 3 * 2!; //6* 2! = 2 * 1!; //2* 1! = 1; //1n! = n * (n - 1)!*/
public class recurrenceDemo1 {public static void main(String[] args) {int n = method(5);System.out.println(n);}public static int method(int n){if(n == 0){ //出口return 1;}else{return n * method(n-1);}}
}
斐波那契数列:
package Recurrence;
/** 古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,* 小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,* 问第二十个月的兔子对数为多少?* 1* 1* 2* 3* 5* 8* 13* 规律:除了第一个月和第二月以外,其余每个月都是前两个月之和* 斐波那契列数**/
public class recurrentDemo2 {public static void main(String[] args) {int m = method(20);System.out.println(m);}public static int method(int n){if(n == 1){return 1;}else if(n==2){return 1;}else{return method(n-1)+method(n-2);}}
}
练习:手动实现FileWriter的try catch异常处理形式的完整模式
package ExceptionDemo;import java.io.FileWriter;
import java.io.IOException;/*手动实现FileWriter的try catch异常处理形式的完整模式*/
public class exceptionTest {public static void main(String[] args) throws IOException {demo();}private static void demo(){FileWriter fileWriter = null;try{fileWriter = new FileWriter("E://a.txt");fileWriter.write("小猫");fileWriter.write("小狗");}catch(Exception e){System.out.println("出现异常");e.printStackTrace();}finally {try {if(fileWriter!=null){fileWriter.close();}}catch(IOException el){el.printStackTrace();}}}public static int get(){try{return 520;}finally {System.out.println("发生异常");}}
}
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
