Java笔记 - 黑马程序员_04(枚举,异常,Collection,List,Set)
枚举
什么是枚举
- 枚举是逐一列举的意思,枚举的作用是进行取值的规范和分类。
- 有限数据的集合,可以使用枚举表示,比如性别,季节,星期,月份等数据。
定义枚举的格式:
public enum 枚举名称{枚举1,枚举2,枚举3...;
}
//举例(表示季节的枚举类)
public enum Season{SPRING,SUMMER,AUTUMN,WINTER;
}
访问枚举值:
//枚举名.枚举值;
Season.SPRING
案例:季节枚举
//1.定义枚举
package com.demo_05枚举;public enum Season {SPRING,SUMER,AUTUMN,WINTER;
}//2.
package com.demo_05枚举;public class MyCalendar {private int year;private int mouth;private int data;private Season season;public MyCalendar(int year, int mouth, int data, Season season) { this.year = year;this.mouth = mouth;this.data = data;this.season = season;}public void show(){System.out.println(year+"年"+mouth+"月"+data+"日"+season);}
}//3.测试类
package com.demo_05枚举;public class Demo {public static void main(String[] args) {MyCalendar m = new MyCalendar(2022,07,10, Season.SPRING);m.show();}
}
1. 异常
1.1 异常的概述
Error:严重问题,不需要处理
Exception:称为异常类,它表示程序本身可以处理的问题
- RuntimeException:在编译期是不检查的,出现问题后,需要我们回来修改代码
- 非RuntimeException:编译期就必须处理的,否则程序不能粉通过编译,就更不能正常运行了
1.2 JVM的默认处理方案
如果程序出现了问题,我们没有做任何处理,最终JVM会做默认的处理
- 把异常的名称,异常原因及异常出现的位置等信息输出在了控制台
- 程序停止执行
1.3 异常处理try…catch…
- 格式:
try{//可能出现异常的代码
}catch(异常类名 变量名){//异常的处理代码
}
- 执行流程
- 程序从try里面的代码开始执行
- 出现异常,会自动生成一个异常类对象,该异常对象将被提交给Java运行时系统
- 当Java运行时系统接收到异常对象时,会到catch中去找匹的异常类,找到后进行异常的处理
- 执行完毕之后,程序还可以继续往下执行
package demo_01;/*try{可能出现异常的代码
}catch(异常类名 变量名){异常的处理代码
}*/
public class ExceptionDemo {public static void main(String[] args) {System.out.println("开始");method();System.out.println("结束");}public static void method() {int[] arr = {15, 22, 66, 88};try {System.out.println(arr[4]); //ArrayIndexOutOfBoundsException}catch(ArrayIndexOutOfBoundsException e){ //new ArrayIndexOutOfBoundsExceptionSystem.out.println("访问的索引越界");e.printStackTrace();}}
}
1.4 Throwable的成员方法
方法名 | 说明 |
---|---|
public String getMessage() | 返回此throwable的详细消息字符串 |
public String toString() | 返回此可抛出的简短描述 |
public void printStackTrace() | 把异常的错误信息输出在控制台 |
package demo_01;/*try{可能出现异常的代码
}catch(异常类名 变量名){异常的处理代码
}*/
public class ExceptionDemo {public static void main(String[] args) {System.out.println("开始");method();System.out.println("结束");}public static void method() {int[] arr = {15, 22, 66, 88};try {System.out.println(arr[4]); //ArrayIndexOutOfBoundsException} catch (ArrayIndexOutOfBoundsException e) { //new ArrayIndexOutOfBoundsException//public String toString()返回此可抛出的简短描述System.out.println(e.toString());System.out.println("------------");//public String getMessage()返回此throwable的详细消息字符串System.out.println(e.getMessage());System.out.println("------------");//public void printStackTrace()把异常的错误信息输出在控制台e.printStackTrace();}}
}
//运行结果
开始
java.lang.ArrayIndexOutOfBoundsException: Index 4 out of bounds for length 4
------------
Index 4 out of bounds for length 4
------------
结束
java.lang.ArrayIndexOutOfBoundsException: Index 4 out of bounds for length 4at demo_01.ExceptionDemo.method(ExceptionDemo.java:18)at demo_01.ExceptionDemo.main(ExceptionDemo.java:11)
1.5 编译时异常和运行时异常的区别
Java中的异常被分为两大类:编译时异常和运行时异常,也被称为受检异常和非受检异常
所有的RuntimeException类及其子类被称为运行时异常,其他的异常都是编译时异常
- 编译时异常:必须显示处理,否则程序就会发生错误,无法通过编译
- 运行时异常:无需显示处理,也可以和编译时异常一样处理
package demo_01;import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;public class ExceptionDemo_02 {public static void main(String[] args) {method();method2();}//编译时异常public static void method() {try {String s = "2022-04-24";SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");Date d = sdf.parse(s);System.out.println(d);} catch (ParseException e) {e.printStackTrace();}}//运行异常public static void method2() {try {int[] arr = {55, 88, 99};System.out.println(arr[3]); //ArrayIndexOutOfBoundsException} catch (ArrayIndexOutOfBoundsException e) {System.out.println("访问索引越界");}}
}
1.6 异常处理之throws
虽然我们通过try…catch…可以对异常进行处理,但是并不是所有的情况我们都有权限进行异常的处理
也就是说,有些时候可能出现的异常是我们处理不了的,这个时候该怎么办呢?
针对这种情况,Java提供了throws的处理方案
- 格式:
throws 异常类名;
注意:这个格式是跟在方法的括号后面的
- 编译时异常必须要进行处理,两种处理方案:try…catch…或者throws,如果采用throws这种方案,将来谁调用谁处理
- 运行时异常可以不处理,出现问题后,需要我们回来修改代码
package demo_01;import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/*throws 异常类名;这个格式跟在方法名的后面
*/
public class ThrowsDemo {public static void main(String[] args) {System.out.println("开始");try {method();} catch (ParseException e) {e.printStackTrace();}System.out.println("结束");}//抛出异常等待调用者去处理 throws ParseException//编译时异常public static void method() throws ParseException {String s = "2022-04-24";SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");Date d = sdf.parse(s);System.out.println(d);}
}
1.7 throw关键字
Java中提供了throw关键字,可以在程序运行过程中,抛出某种特定的异常。
格式:throw new异常类名();
// 注意:throw异常以后,后面的代码将停止执行
产生异常的意义
- 在方法中,当传递的参数有误,程序没有运行下去的意义时,可以直接抛出异常,结束方法
- 告知调用者方法中出现了问题,让调用者修改代码逻辑
public class Demo1 {public static void main(String[] args) {getResule(10,0);//调用testtry {test(10,0);} catch (Exception e) {e.printStackTrace();}}//throw是在内部的方法,根据业务情况,产生某种异常,让程序停止public static int getResule(int a,int b){if (b!=0){return a / b;}else {//产生运行时异常,和return效果一样,都可以让方法停止,但是作用不一样,throw是告知使用者代码有问题,throw new RuntimeException("除数不能为0");}}public static int test(int a,int b) throws Exception{if (b!=0){return a / b;}else {//产生编译时异常,需要在方法上面做声明throw new Exception("除数不能为0");}}
1. 8 throws和throw的区别
throws | throw |
---|---|
用在方法声明后面,跟的是异常类名 | 用在方法体内,跟的是异常对象名 |
表示抛出异常,由该方法的调用者来处理 | 表示抛出异常,由方法体内的语句处理 |
表示出现异常的一种可能性,并不一定会发生这些异常 | 执行throw一定抛出了某种异常 |
1.9 自定义异常
- 格式
//格式
public class 异常类名 extends Exception{//无参构造//带参构造
}
//范例
public class ScoreException extends Exception{public ScoreException(){}public ScoreException(String message){super(message);}
}
//1.
package scoreDemo;public class ScoreException extends Exception{public ScoreException() {}public ScoreException(String message) {super(message);}
}//2.
package scoreDemo;public class Teacher {public void checkScore(int score) throws ScoreException{if (score<0||score>100){throw new ScoreException("分数输入的不正确");}else {System.out.println("分数正确");}}
}//3.
package scoreDemo;import java.util.Scanner;public class TeacherDemo {public static void main(String[] args) {Scanner sc = new Scanner(System.in);System.out.print("请输入分数:");int score = sc.nextInt();Teacher t= new Teacher();try {t.checkScore(score);} catch (ScoreException e) {e.printStackTrace();}}
}
//运行结果
请输入分数:98
分数正确请输入分数:150
scoreDemo.ScoreException: 分数输入的不正确at scoreDemo.Teacher.checkScore(Teacher.java:6)at scoreDemo.TeacherDemo.main(TeacherDemo.java:13)
2.Collection
集合的特点:提供一种存储空间可变的存储模型,存储的数据容量可以随时发生改变
2.1 集合体系结构
2.2 Collection集合概述和使用
Collection集合概述
- 是单列集合的顶层接口,它表示一组对象,这些对象也称为Collection的元素
- JDK不提供此接口的任何直接实现,它提供更具体的子接口(如Set和List)实现
创建Collection集合的对象
- 多态的方式
- 具体的实现类ArrayList
package collectionDemo_01;import java.util.ArrayList;
import java.util.Collection;/*
创建Collection集合对象
多态的方式
*/public class CollectionDemo {public static void main(String[] args) {Collection<String> c = new ArrayList<String>();c.add("张三");c.add("李四");c.add("王五");System.out.println(c);}
}
//运行结果
[张三, 李四, 王五]
2.3 Collection集合常用方法
方法名 | 说明 |
---|---|
boolean add(E e) | 添加元素 |
boolean remove(Object o) | 从集合中移除指定的元素 |
void clear() | 清空集合中的元素 |
boolean contains(Object o) | 判断集合中是否存在指定的元素 |
boolean isEmpty() | 判断集合是否为空 |
int size() | 集合的长度,也就是集合中元素的个数 |
2.4 Collection集合的遍历
Iterator:迭代器,集合的专用遍历方式
- Iterator iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到
- 迭代器是通过集合的iterator()方法得到的,所以我们说它是依赖于集合而存在的
Iterator中的常用方法
- E next():返回迭代中的下一个元素
- boolean hasNext():如果迭代具有更多元素,则返回true
package collectionDemo_01;import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;/*
创建Collection集合对象
多态的方式
*/public class CollectionDemo {public static void main(String[] args) {Collection<String> c = new ArrayList<String>();c.add("张三");c.add("李四");c.add("王五");Iterator<String> it = c.iterator();//用while循环改进判断while(it.hasNext()){String n = it.next();System.out.println(n);}}
}
//运行结果
张三
李四
王五
2.5 集合的使用步骤
2.6 Collection集合存储学生对象并遍历
需求:创建一个存储学生对象的集合,存储3个学生对像,使用程序实现在控制台遍历该集合
思路:
①定义学生类
②创建Collection集合对像
③创建学生对象
④把学生添加到集合
⑤遍历集合(迭代器方式)
//1.定义学生类
package demo_02;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;}
}//2.测试类
package demo_02;import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;public class CollectionDemo {public static void main(String[] args) {//创建Colection集合对象Collection<Student> c = new ArrayList<Student>();//创建学生对象Student sc1 = new Student("张三", 18);Student sc2 = new Student("李四", 19);Student sc3 = new Student("王五", 10);//把学生添加到集合c.add(sc1);c.add(sc2);c.add(sc3);//遍历集合(迭代器方式)Iterator<Student> it = c.iterator();while(it.hasNext()){Student n = it.next();System.out.println(n.getName()+", "+n.getAge());}}
}
//运行结果
张三, 18
李四, 19
王五, 10
3. List
3.1 List集合概述和特点
List集合概述:
- 有序集合(也称为序列),用户可以精确控制列表中每个元素的插入位置。用户可以通过整数索引访问元素,并搜索列表中的元素
- 与Set集合不同,列表通常允许重复的元素
List集合特点:
- 有序:存储和取出的元素顺序一致
- 可重复:存储的元素可以重复
package listDemo_03;/*List集合特点:有序:存储和取出的元素顺序一致可重复:存储的元素可以重复*/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<>();//添加元素list.add("张三");list.add("李四");list.add("王五");list.add("王五");//输出集合对象System.out.println(list);//迭代器遍历集合Iterator<String> it = list.iterator();while (it.hasNext()) {String s = it.next();System.out.println(s);}}
}
//运行结果
[张三, 李四, 王五, 王五]
张三
李四
王五
王五
3.2 List集合特有方法
方法名 | 说明 |
---|---|
void add(int index,E element) | 在此集合中的指定位置插入指定的元素 |
E remove(int index) | 删除指定索引处的元素,返回被删除的元素 |
E set(int index,E element) | 修改指定索引处的元素,返回被修改的元素 |
E get(int index) | 返回指定索引处的元素 |
3.3 list集合存储学生对象并遍历
需求:创建一个存储学生对象的集合,存储3个学生对像,使用程序实现在控制台遍历该集合
思路:
①定义学生类
②创建List集合对象
③创建学生对象
④把学生添加到集合
⑤遍历集合(迭代器方式,for循环方式)
//1.创建学生对象
package demo_02;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;}
}//2.测试类
package demo_02;import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;/*List集合特点:有序:存储和取出的元素顺序一致可重复:存储的元素可以重复*/public class ListDemo {public static void main(String[] args) {//创建list集合List<Student> list = new ArrayList<>();//创建学生对象Student sc1 = new Student("张三", 18);Student sc2 = new Student("李四", 19);Student sc3 = new Student("王五", 10);//把学生添加到集合list.add(sc1);list.add(sc2);list.add(sc3);//遍历集合(迭代器方式)Iterator<Student> it = list.iterator();while(it.hasNext()){Student n = it.next();System.out.println(n.getName()+", "+n.getAge());}System.out.println("------------");//for循环遍历for (int i = 0;i<list.size(); i++){Student s = list.get(i);System.out.println(s.getName()+", "+s.getAge());}}
}
//运行结果
张三, 18
李四, 19
王五, 10
------------
张三, 18
李四, 19
王五, 10
3.4 Listlterator
Listlterator:列表迭代器
- 通过List集合的listlterator()方法得到,所以说它是List集合特有的迭代器
- 用于允许程序员沿任一方向遍历列表的列表迭代器,在迭代期间修改列表,并获取巧列表中迭代器的当前位置
Listlterator中的常用方法:
方法名 | 说明 |
---|---|
E next() | 返回迭代中的下一个元素 |
boolean hasNext() | 如果迭代具有更多元素,则返回true |
E previous() | 返回列表中的上一个元素 |
boolean hasPrevious() | 如果此列表迭代器在相反方向遍历列表时具有更多元素,则返回true |
void add(E e) | 将指定的元素插入列表 |
package listDemo_03;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<>();//添加元素list.add("张三");list.add("李四");list.add("王五");//通过list集合的listIterator()方法得到ListIterator<String> lit = list.listIterator();while (lit.hasNext()){String n = lit.next();System.out.println(n);}System.out.println("----------");//反向遍历while (lit.hasPrevious()){String b = lit.previous();System.out.println(b);}}
}
//运行结果
张三
李四
王五
----------
王五
李四
张三
3.5 增强for循环
增强for:简化数组和Collection集合的遍历
- 实现Iterable接口的类允许其对象成为增强型for语句的目标
- 它是DKS之后出现的,其内部原理是一个lterator迭代器
增强for的格式:
//格式:
for(元素数据类型变量名:数组或者Collection集合){//在此处使用变量即可,该变量就是元素
}//范例:
int[] arr={1,2,3,4,5};
for(int i:arr){System.out.printIn(i)
}
3.6 案例:List集合存储学生对像用三种方式遍历
需求:创建一个存储学生对象的集合,存储3个学生对像,使用程序实现在控制台遍历该集合
思路:
①定义学生类
②创建List集合对象
③创建学生对象
④把学生添加到集合
⑤遍历集合
迭代器:集合特有的遍历方式
普通for:带有索引的遍历方式
增强for:最方使的遍历方式
//1.创建学生类
package demo_02;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;}
}//2.测试类
package demo_02;import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;/*List集合特点:有序:存储和取出的元素顺序一致可重复:存储的元素可以重复*/public class ListDemo {public static void main(String[] args) {//创建list集合List<Student> list = new ArrayList<>();//创建学生对象Student sc1 = new Student("张三", 18);Student sc2 = new Student("李四", 19);Student sc3 = new Student("王五", 10);//把学生添加到集合list.add(sc1);list.add(sc2);list.add(sc3);//遍历集合(迭代器方式)Iterator<Student> it = list.iterator();while (it.hasNext()) {Student n = it.next();System.out.println(n.getName() + ", " + n.getAge());}System.out.println("------------");//for循环遍历for (int i = 0; i < list.size(); i++) {Student s = list.get(i);System.out.println(s.getName() + ", " + s.getAge());}System.out.println("------------");//增强for循环for (Student sc : list) {System.out.println(sc.getName() + ", " + sc.getAge());}}
}
//3.运行结果
张三, 18
李四, 19
王五, 10
------------
张三, 18
李四, 19
王五, 10
------------
张三, 18
李四, 19
王五, 10
3.7 数据结构
- 数据结构是计算机存储、组织数据的方式。是指相互之间存在一种或多种特定关系的数据元素的集合
- 通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率
3.8 常见数据结构之栈
- 数据进入栈模型的过程称为:压/进栈
- 数据离开栈模型的过程称为:弹/出栈
- 栈是一种数据先进后出的模型
3.9 常见数据结构之队列
- 数据从后端进入队列模型的过程称为:入队列
- 数据从前端离开队列模型的过程称为:出队列
- 队列是一种数据先进先出的模型
3.10 常见数据结构之数组
- 数组是一种查询快,增删慢的模型
- 查询数据通过索引定位,查询任意数据耗时相同,查询效率高
- 删除数据时,要将原始数据删除,同时后面每个数据前移,删除效率低
- 添加数据时,添加位置后的每个数据后移,再添加元素,添加效率极低
3.11 常见数据结构之链表
3.11.1 添加数据
在数据AC之间添加一个数据B,保存在地址54位置
- 在数据B对应的下一个数据地址指向数据C
- 在数据A对应的下一个数据地址指向数据B
3.11.2 删除数据
在数据AC之间添加一个数据B,保存在地址54位置,删除数据BD之间的数据C
- 数据B对应的下一个数据地址指向数据D
- 数据C删除
3.11.3 链表查询
- 查询数据D是否存在,必须从头(head)开始查询
- 查询第3个数据,必须从头(head)开始查询
- 链表是一种增删快的模型(对比数组)
- 链表是一种查询慢的模型(对比数组)
3.12 List集合子类特点
List集合常用子类:ArrayList, LinkedList
- ArrayList::底层数据结构是数组,查询快,增删慢
- LinkedList:底层数据结构是链表,查询慢,增删快
练习:
分别使用ArrayLista和LinkedList完成存储字符串并遍历
package myList;import java.util.ArrayList;
import java.util.LinkedList;public class ListDemo {public static void main(String[] args) {//创建ArrayList集合对象ArrayList<String> array= new ArrayList<String>();array.add("张三");array.add("李四");array.add("hello");//遍历集合for (String s : array){System.out.println(s);}System.out.println("--------------");//创建LinkedList集合对象LinkedList<String> linkedList = new LinkedList<String>();linkedList.add("hello");linkedList.add("world");linkedList.add("java");//遍历集合for (String c : linkedList){System.out.println(c);}}
}
//运行结果
张三
李四
hello
--------------
hello
world
java
3.13 案例:ArrayList集合存储学生对象用三种方式遍历
需求:创建一个存储学生对象的集合,存储3个学生对像,使用程序实现在控制台遍历该集合
思路:
①定义学生类
②创建ArrayList集合对像
③创建学生对象
④把学生添加到集合
⑤遍历集合
迭代器:集合特有的遍历方式
普通for:带有索引的遍历方式
增强for:最方便的遍历方式
//1.创建学生类
package demo_02;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;}
}//2.测试类(创建ArrayList集合对象)
package demo_02;import java.util.ArrayList;
import java.util.Iterator;public class ArrayListDemo {public static void main(String[] args) {//创建ArrayList集合对象ArrayList<Student> array = new ArrayList<Student>();//创建学生对象Student sc1 = new Student("张三", 18);Student sc2 = new Student("李四", 19);Student sc3 = new Student("王五", 10);//把学生添加到集合array.add(sc1);array.add(sc2);array.add(sc3);//迭代器方式遍历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 i = 0; i<array.size(); i++){Student s1 = array.get(i);System.out.println(s1.getName()+", "+ s1.getAge());}System.out.println("-----------");//增强forfor (Student s2 : array){System.out.println(s2.getName()+", "+ s2.getAge());}}
}
//运行结果
张三, 18
李四, 19
王五, 10
-----------
张三, 18
李四, 19
王五, 10
-----------
张三, 18
李四, 19
王五, 10
3.14 LinkedList集合的特有功能
方法名 | 说明 |
---|---|
public void addFirst(E e) | 在该列表开头插入指定的元素 |
public void addLast(E e) | 将指定的元素追加到此列表的末尾 |
public E getFirst() | 返回此列表中的第一个元素 |
public E getLast() | 返回此列表中的最后一个元素 |
public E removeFirst() | 从此列表中删除并返回第一个元素 |
public E removeLast() | 从此列表中删除并返回最后一个元素 |
package myList;import java.util.LinkedList;
/*public void addFirst(E e) 在该列表开头插入指定的元素public void addLast(E e) 将指定的元素追加到此列表的末尾public E getFirst() 返回此列表中的第一个元素public E getLast() 返回此列表中的最后一个元素public E removeFirst() 从此列表中删除并返回第一个元素public E removeLast() 从此列表中删除并返回最后一个元素
*/
public class LinkdeListDemo {public static void main(String[] args) {//创建LinkdeList集合对象LinkedList<String> linkdeList = new LinkedList<String>();linkdeList.add("hello");linkdeList.add("world");linkdeList.add("java");/* public void addFirst(E e) 在该列表开头插入指定的元素public void addLast(E e) 将指定的元素追加到此列表的末尾*/linkdeList.addFirst("javase");linkdeList.addLast("javaee");/* public E getFirst() 返回此列表中的第一个元素public E getLast() 返回此列表中的最后一个元素*/System.out.println(linkdeList.getFirst());System.out.println(linkdeList.getLast());/*public E removeFirst() 从此列表中删除并返回第一个元素public E removeLast() 从此列表中删除并返回最后一个元素*/System.out.println(linkdeList.removeFirst());System.out.println(linkdeList.removeLast());}
}
//运行结果
javase
javaee
javase
javaee
4. set
4.1 set集合的概述和特点
Set集合特点
- 不包含重复元素的集合
- 没有带索引的方法,所以不能使用普通for循环遍历
Set集合练习:
- 存储字符串并遍历
package demo_01;/*
Set集合特点不包含重复元素的集合没有带索引的方法,所以不能使用普通o循环遍历HashSet:对集合的迭代顺序不作任何保证
*/import java.util.HashSet;
import java.util.Set;public class SetDemo {public static void main(String[] args) {//创建集合对象Set<String> set = new HashSet<String>();//添加元素set.add("hello");set.add("java");set.add("world");//不包含重复元素set.add("java");//遍历for (String s : set) {System.out.println(s);}}
}
//运行结果
java
world
hello
4.2 哈希值
哈希值:是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
Object类中有一个方法可以获取对象的哈希值
- public int hashCode():返回对象的哈希码值
对象的哈希值特点
- 同一个对象多次调用hashCode()方法返回的哈希值是相同的
- 默认情况下,不同对象的哈希值是不同的。而重写hashCode()方法,可以实现让不同对象的哈希值相同
//1.
package demo_02;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;}/* 重写equals()和hashCode()方法@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;if (age != student.age) return false;return name != null ? name.equals(student.name) : student.name == null;}@Overridepublic int hashCode() {int result = name != null ? name.hashCode() : 0;result = 31 * result + age;return result;}*/
}//2.
package demo_02;public class HashDemo {public static void main(String[] args) {//创建学生对象Student s1 = new Student("张三",18);//同一个对象多次调用HashCode()方法返回的哈希值是相同的System.out.println(s1.hashCode()); //1239731077System.out.println(s1.hashCode()); //1239731077Student s2 = new Student("张三",18);//默认情况下,不同对象的哈希值不同//通过方法重写,可以实现不同对象的哈希值相同(重写equals()和hashCode()方法)System.out.println(s2.hashCode()); //557041912System.out.println("-----------");System.out.println("java".hashCode()); //3254818System.out.println("world".hashCode()); //113318802System.out.println("java".hashCode()); //3254818System.out.println("-----------");System.out.println("重地".hashCode()); //1179395System.out.println("通话".hashCode()); //1179395}
}
4.3 HashSet:集合概述和特点
HashSet集合特点:
- 底层数据结构是哈希表
- 对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致
- 没有带索引的方法,所以不能使用普通for循环遍历
- 由于是Set集合,所以是不包含重复元素的集合
HashSet集合练习:
- 存储字符串并遍历
package demo_03;import java.util.HashSet;public class HashSetDemo {public static void main(String[] args) {//创建集合对象HashSet<String> hs = new HashSet<String>();//添加元素hs.add("hello");hs.add("world");hs.add("java");//set集合,不包含重复的元素hs.add("world");//遍历for (String s : hs) {System.out.println(s);}}
}
//运行结果
world
java
hello
4.4 常见数据结构之哈希表
哈希表
- JDK8之前,底层采用数组+链表实现,可以说是一个元素为链表的数组
- JDK8以后,在长度比较长的时候,底层实现了优化
4.5 案例:HashSet集合存储学生对像并遍历
需求:创建一个存储学生对象的集合,存储多个学生对象,使用程序实现在控制台遍历该集合
要求:学生对象的成员变量值相同,我们就认为是同一个对像
思路:
①定义学生类
②创建HashSet集合对象
③创建学生对像
④把学生添加到集合
⑤遍历集合(增强for)
⑥在学生类中重写两个方法
hashCode()和equals()
自动生成即可
//1.
package demo_03;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;}//重写equals()和hashCode()方法@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;if (age != student.age) return false;return name != null ? name.equals(student.name) : student.name == null;}@Overridepublic int hashCode() {int result = name != null ? name.hashCode() : 0;result = 31 * result + age;return result;}
}//2.
package demo_03;import java.util.HashSet;public class HashSetStuDemo {public static void main(String[] args) {//创建集合对象HashSet<Student> hs = new HashSet<Student>();//创建学生对象Student s1 =new Student("张三", 18);Student s2 =new Student("李四", 20);Student s3 =new Student("王五", 19);//重写equals()和hashCode()方法,集合元素不会重复出现Student s4 =new Student("李四", 20);//添加学生元素到集合hs.add(s1);hs.add(s2);hs.add(s3);hs.add(s4);//遍历for (Student sc:hs){System.out.println(sc.getName()+", "+sc.getAge());}}
}
//运行结果
王五, 19
张三, 18
李四, 20
4.6 LinkedHashSet:集合概述和特点
LinkedHashSet集合特点
- 哈希表和链表实现的Set接口,具有可预测的迭代次序
- 由链表保证元素有序,也就是说元素的存储和取出顺序是一致的
- 由哈希表保证元素唯一,也就是说没有重复的元素
LinkedHashSet:集合练习
- 存储字符串并遍历
package demo_04;import java.util.LinkedHashSet;public class LinkedHashSetDemo {public static void main(String[] args) {//创建集合对象LinkedHashSet<String> linkedHashSet = new LinkedHashSet<String>();//添加元素linkedHashSet.add("hello");linkedHashSet.add("world");linkedHashSet.add("java");//哈希表保证元素的唯一性,也就是说没有重复的元素linkedHashSet.add("world");//遍历for (String s:linkedHashSet){System.out.println(s);}}
}
//运行结果
hello
world
java
4.7 TreeSet集合概述和特点
TreeSet:集合特点:
- 元素有序,这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方式取决于构造方法
(1) TreeSet():根据其元素的自然排序进行排序
(2) TreeSet(Comparator comparator):根据指定的比较器进行排序
- 没有带索引的方法,所以不能使用普通for循环遍历
- 由于是Set集合,所以不包含重复元素的集合
TreeSet集合练习:
- 存储整数并遍历
package demo_05;import java.util.TreeSet;public class TreeSetDemo {public static void main(String[] args) {//创建集合对象TreeSet<Integer> treeSet = new TreeSet<Integer>();//TreeSet():根据其元素的自然排序进行排序//添加元素treeSet.add(10);treeSet.add(50);treeSet.add(30);treeSet.add(20);treeSet.add(40);//遍历for (Integer s : treeSet) {System.out.println(s);}}
}
//运行结果
10
20
30
40
50
4.8 自然排序Comparable的使用
- 存储学生对像并遍历,创建TreeSet集合使用无参构造方法
- 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
结论:
- 用TreeSet集合存储自定义对像,无参构造方法使用的是自然排序对元素进行排序的
- 自然排序,就是让元素所属的类实现Comparable接口,重写compareTo(To)方法
- 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
//1.学生对象
package demo_05;
//该接口对实现它的每个类的对象强加一个整体排序。 这个排序被称为类的自然排序 ,类的compareTo方法被称为其自然比较方法 。
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;}@Overridepublic int compareTo(Student s) {//return 0; 返回0表示元素重复,只会添加第一个元素,不会添加其他元素//return 1; 按照存储的顺序输出(升序)//return -1; (降序)//按照年龄从小到大排序int num = this.age - s.age; //(升序)//int num = s.age - this.age;(降序)//年龄相同时,按照姓名的字母顺序排序int num2 = num == 0?this.name.compareTo(s.name):num;return num2;}
}//2.测试类
package demo_05;import java.util.TreeSet;
/*
存储学生对像并遍历,创建TreeSet集合使用无参构造方法
要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
*/
public class TreeSetDemo02 {public static void main(String[] args) {//创建集合对象TreeSet<Student> ts = new TreeSet<Student>();//创建学生对象Student s1 = new Student("xishi", 18);Student s2 = new Student("wangzhaojun", 19);Student s3 = new Student("diaochan", 20);Student s4 = new Student("yangyuhuan", 16);Student s5 = new Student("chenghanhan", 20);//学生对象添加到集合ts.add(s1);ts.add(s2);ts.add(s3);ts.add(s4);ts.add(s5);//遍历for (Student s : ts) {System.out.println(s.getName() + ", " + s.getAge());}}
}
//运行结果
yangyuhuan, 16
xishi, 18
wangzhaojun, 19
chenghanhan, 20
diaochan, 20
4.9 比较器排序Comparator的使用
- 存储学生对象并遍历,创建TreeSet集合使用带参构造方法
- 要求:按照年龄从小到大排序,年龄相同时,按姓名的字母顺序排序
结论:
- 用TreeSet集合存储自定义对象,带参构造方法使用的是比较器排序对元素进行排序的
- 比较器排序,就是让集合构造方法接收Comparator的实现类对象,重写compare(To1,To2)方法
- 重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
//1.创建学生类
package demo_06;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;}
}//2.测试类
package demo_06;import java.util.Comparator;
import java.util.TreeSet;
/*
- 存储学生对象并遍历,创建TreeSet集合使用带参构造方法
- 要求:按照年龄从小到大排序,年龄相同时,按姓名的字母顺序排序
*/
public class TreeSetDemo {public static void main(String[] args) {//创建集合对象TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {//创建匿名对象@Overridepublic int compare(Student o1, Student o2) {//按照年龄从小到大排序int num = o1.getAge() - o2.getAge();//年龄相同时,按姓名的字母顺序排序int num2 = num == 0?o1.getName().compareTo(o2.getName()):num;return num2;}});//创建学生对象Student s1 = new Student("xishi", 18);Student s2 = new Student("wangzhaojun", 19);Student s3 = new Student("diaochan", 20);Student s4 = new Student("yangyuhuan",22);Student s5 = new Student("chenghanhan", 20);//学生对象添加到集合ts.add(s1);ts.add(s2);ts.add(s3);ts.add(s4);ts.add(s5);//遍历for (Student s : ts) {System.out.println(s.getName() + ", " + s.getAge());}}
}
//运行结果
xishi, 18
wangzhaojun, 19
chenghanhan, 20
diaochan, 20
yangyuhuan, 22
4.10 案例:成绩排序
- 需求:用TreeSet集合存储多个学生信息(姓名,语文成绩,数学成绩,并遍历该集合)
- 要求:按照总分从高到低出现
思路:
①定义学生类
②创建TreeSet集合对象,通过比较器排序进行排序
③创建学生对象
④把学生对象添加到集合
⑤遍历集合
//1.创建学生类
package demo_07;public class Student {private String name;private int chinese;private int math;public Student() {}public Student(String name, int chinese, int math) {this.name = name;this.chinese = chinese;this.math = math;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getChinese() {return chinese;}public void setChinese(int chinese) {this.chinese = chinese;}public int getMath() {return math;}public void setMath(int math) {this.math = math;}public int sum(){ //求和方法return chinese+math;}
}//2.测试类
package demo_07;import java.util.Comparator;
import java.util.TreeSet;
/*
- 需求:用TreeSet:集合存储多个学生信息(姓名,语文成绩,数学成绩,并遍历该集合
- 要求:按照总分从高到低出现
*/
public class TreeSetDemo {public static void main(String[] args) {//创建集合对象,通过比较器排序进行排序TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {int num = o1.sum() - o2.sum();int num2 = num == 0?o1.getName().compareTo(o2.getName()):num;return num2;}});//创建学生对象Student s1 = new Student("张三",98,99);Student s2 = new Student("李四",95,95);Student s3 = new Student("王五",95,99);Student s4 = new Student("小陈",98,100);Student s5 = new Student("小尚",100,99);Student s6 = new Student("逸乐",95,99);//添加学生对象到集合ts.add(s1);ts.add(s2);ts.add(s3);ts.add(s4);ts.add(s5);ts.add(s6);//遍历for (Student s:ts){System.out.println(s.getName()+", "+s.getChinese()+", "+s.getMath()+", "+s.sum());}}
}
//运行结果
李四, 95, 95, 190
王五, 95, 99, 194
逸乐, 95, 99, 194
张三, 98, 99, 197
小陈, 98, 100, 198
小尚, 100, 99, 199
4.11 案例:不重复的随机数
需求:编写一个程序,获取10个1-20之间的随机数,要求随机数不能重复,并在控制台输出
思路:
①创建Set集合对象
②创建随机数对象
③判断集合的长度是不是小于10
是:产生一个随机数,添加到集合
回到3继续
④遍历集合
package demo_07;import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;public class SetDemo {public static void main(String[] args) {//创建集合对象//Set<Integer> set = new HashSet<Integer>();Set<Integer> set = new TreeSet<Integer>();//创建随机数对象Random r = new Random();//判断集合长度是否小于10while (set.size() < 10) {int num = r.nextInt(20) + 1;set.add(num);}//遍历for (Integer i : set) {System.out.println(i);}}
}
更多内容请访问博主博客:逸乐的博客 - 今晚一起吃火锅
文章如有纰漏请指出,整理不易多多包涵。
Java后续笔记将持续更新…
Java笔记 - 黑马程序员_04(枚举,异常,Collection,List,Set)相关推荐
- Java笔记 - 黑马程序员_08(Lambda表达式,接口组成更新,方法引用,类加载器,反射)
1. Lambda 1.1 函数式编程思想概述 在数学中,函数就是有输入量.输出量的一套计算方案,也就是"数据做操作" 面向对象思想强调"必须通过对象的形式来做事情&qu ...
- [学习笔记]黑马程序员-Hadoop入门视频教程
文章目录 参考资料 第一章:大数据导论与Linux基础(p1-p17) 1.1 大数据导论 1.1.1 企业数据分析方向 1.1.2 数据分析基本流程步骤 明确分析的目的和思路 数据收集 数据处理 数 ...
- Java教程-黑马程序员版
很多初学Java的小伙伴,在选择Java教程的时候有很多困惑.哪一套Java教程更适合入门?某一个技术学完之后能做什么?黑马程序员为大家整理了2022年Java教程的选择建议.希望对大家有帮助~ 如果 ...
- [学习笔记]黑马程序员python教程
文章目录 思维导图 Python基础知识图谱 面向对象 SQL入门和实战 Python高阶技巧 第一阶段 第九章:Python异常.模块与包 1.9.1异常的捕获 1.9.1.1 为什么要捕获异常 1 ...
- [学习笔记]黑马程序员Spark全套视频教程,4天spark3.2快速入门到精通,基于Python语言的spark教程
文章目录 视频资料: 思维导图 一.Spark基础入门(环境搭建.入门概念) 第二章:Spark环境搭建-Local 2.1 课程服务器环境 2.2 Local模式基本原理 2.3 安装包下载 2.4 ...
- c语言笔记——黑马程序员上课笔记
C语言概述 1.1 什么是C语言 一提到语言这个词语,自然会想到的是像英语.汉语等这样的自然语言,因为它是人和人交换信息不可缺少的工具. 而今天计算机遍布了我们生活的每一个角落,除了人和人的相互交流之 ...
- 黑马程序员_常见异常
--------------------android培训.java 培训.期待与您交流! ---------------------- 算术异常类:ArithmeticExecption 空指针异常 ...
- Node.js学习笔记 [黑马程序员]——day34
文章目录 初识 Express 简介 Express 的基本使用 托管静态资源 nodemon Express 路由 路由的概念 :dog:什么是路由 :dog:Express 中的路由 :dog: ...
- Node.js学习笔记 [黑马程序员]——day2
文章目录 模块化的基本概念 模块化规范 Node.js 中模块的分类 Node.js 中模块的分类 加载模块 Node.js 中的模块作用域 向外共享模块作用域中的成员 `module` 对象 `mo ...
- 笔记 黑马程序员C++教程从0到1入门编程——基础语法入门
目录 1.C++初识 02 C++书写helloworld 03 注释 04 变量 05 常量 06 关键字 07 标识符命名规则 2.数据类型 08 整型 09 sizeof关键字 10 实型(浮点 ...
最新文章
- android contentresolver权限,求助关于getcontentresolver().query()
- 设计模式之外观模式(Facade)摘录
- JS脚本语言 JavaScript
- Java Script 学习笔记(一)
- java原型链_深入总结Javascript原型及原型链
- ajax拼接显示不同样式,Ajax重点整理
- java面试题35 给定以下JAVA代码,这段代码运行后输出的结果是()
- java张int 和 Integer的区别
- 阿里Q2财报:阿里云势头猛进领跑全球
- History命令的显示带时间
- linux源码编译ipk,Ubuntu亲自手动编译Openwrt (DreamBox): for njit....ipk
- 计算机进pe按键,台式机进入pe按什么键
- pythonidle怎么设置_Python IDLE基本设置
- WFP 样式(复习用)
- python做相册_动感网页相册 python编写简单文件夹内图片浏览工具
- 用Excel完成专业化数据统计、分析工作
- uniapp 简易的商品分类垂直分类(单项联动)
- matlab傅里叶级数展开
- springboot+shiro is not eligible for getting processed by all BeanPostProcessors
- 奥比中光深度摄像头_乐视三合一奥比中光Orbbec Astra Pro在ROS中配置显示RGB、深度、IR图像的两种思路...
热门文章
- Linux服务器重启导致数据丢失问题解决
- 计算机无法安装u盘驱动,Win7提示“无法成功安装设备驱动程序”,解决无法安装USB驱动程序的问题!...
- Akka 指南 之「Actors」
- 英语读音(二) / English Pronounciation
- Android实战——一步一步实现流动的炫彩边框
- Micrometer中文文档
- Pandas DataFrame为什么弃用.ix【个人看法】
- 特网云 DirectAdmin 安装SSL
- Web前端大作业——城旅游景点介绍(HTML+CSS+JavaScript) html旅游网站设计与实现
- 基于PHP的定时交作业系统