基本类型包装类的作用
将基本数据类型封装成对象的好处在于可以在对象中定义更多的功能方法操作该数据
常用的操作之一:用于基本数据类型与字符串之间的转换
基本类型对应的包装类
基本数据类型 | 包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
Integer类概述
包装一个对象中的原始类型 int 的值
Integer类构造方法
方法名 | 说明 |
---|---|
public Integer(int value) | 根据 int 值创建 Integer 对象(过时) |
public Integer(String s) | 根据 String 值创建 Integer 对象(过时) |
public static Integer valueOf(int i) | 返回表示指定的 int 值的 Integer 实例 |
public static Integer valueOf(String s) | 返回一个保存指定值的 Integer 对象 String |
示例代码
public class IntegerDemo { public static void main(String[] args) { //public Integer(int value):根据 int 值创建 Integer 对象(过时) Integer i1 = new Integer(100); System.out.println(i1); //public Integer(String s):根据 String 值创建 Integer 对象(过时) Integer i2 = new Integer("100"); // Integer i2 = new Integer("abc"); //NumberFormatException System.out.println(i2); System.out.println("--------"); //public static Integer valueOf(int i):返回表示指定的 int 值的 Integer 实例 Integer i3 = Integer.valueOf(100); System.out.println(i3); //public static Integer valueOf(String s):返回一个保存指定值的Integer对象String Integer i4 = Integer.valueOf("100"); System.out.println(i4); }
}
int转换为String
转换方式
示例代码
public class IntegerDemo { public static void main(String[] args) { //int --- String int number = 100; //方式1 String s1 = number + ""; System.out.println(s1); //方式2 //public static String valueOf(int i) String s2 = String.valueOf(number); System.out.println(s2); System.out.println("--------"); }
}
String转换为int
转换方式
方式一:先将字符串数字转成Integer,再调用valueOf()方法
方式二:通过Integer静态方法parseInt()进行转换
示例代码
public class IntegerDemo { public static void main(String[] args) { //String --- int String s = "100"; //方式1:String --- Integer --- int Integer i = Integer.valueOf(s); //public int intValue() int x = i.intValue(); System.out.println(x); //方式2 //public static int parseInt(String s) int y = Integer.parseInt(s); System.out.println(y); }
}
案例需求
有一个字符串:“91 27 46 38 50”,请写程序实现最终输出结果是:“27 38 46 50 91”
代码实现
public class IntegerTest { public static void main(String[] args) { //定义一个字符串 String s = "91 27 46 38 50"; //把字符串中的数字数据存储到一个int类型的数组中 String[] strArray = s.split(" "); // for(int i=0; i<strArray.length; i++) { // System.out.println(strArray[i]); // } //定义一个int数组,把 String[] 数组中的每一个元素存储到 int 数组中 int[] arr = new int[strArray.length]; for(int i=0; i<arr.length; i++) { arr[i] = Integer.parseInt(strArray[i]); }//对 int 数组进行排序 Arrays.sort(arr); //把排序后的int数组中的元素进行拼接得到一个字符串,这里拼接采用StringBuilder来实现 StringBuilder sb = new StringBuilder(); for(int i=0; i<arr.length; i++) { if(i == arr.length - 1) { sb.append(arr[i]); } else { sb.append(arr[i]).append(" "); } }String result = sb.toString();//输出结果 System.out.println(result);}
}
自动装箱
把基本数据类型转换为对应的包装类类型
自动拆箱
把包装类类型转换为对应的基本数据类型
示例代码
Integer i = 100; // 自动装箱
i += 200; // i = i + 200; i + 200 自动拆箱;i = i + 200; 是自动装箱
Date类概述
Date 代表了一个特定的时间,精确到毫秒
Date类构造方法
方法名 | 说明 |
---|---|
public Date() | 分配一个 Date对象,并初始化,以便它代表它被分配的时间,精确到毫秒 |
public Date(long date) | 分配一个 Date对象,并将其初始化为表示从标准基准时间起指定的毫秒数 |
示例代码
public class DateDemo01 { public static void main(String[] args) { //public Date():分配一个 Date对象,并初始化,以便它代表它被分配的时间,精确到毫秒 Date d1 = new Date(); System.out.println(d1); //public Date(long date):分配一个 Date对象,并将其初始化为表示从标准基准时间起 指定的毫秒数long date = 1000*60*60; Date d2 = new Date(date); System.out.println(d2); }
}
常用方法
方法名 | 说明 |
---|---|
public long getTime() | 获取的是日期对象从1970年1月1日 00:00:00到现在的毫秒值 |
public void setTime(long time) | 设置时间,给的是毫秒值 |
示例代码
public class DateDemo02 { public static void main(String[] args) { //创建日期对象 Date d = new Date(); //public long getTime():获取的是日期对象从1970年1月1日 00:00:00到现在的毫秒值 // System.out.Time()); // System.out.Time() * 1.0 / 1000 / 60 / 60 / 24 / 365 + "年"); //public void setTime(long time):设置时间,给的是毫秒值 // long time = 1000*60*60; long time = System.currentTimeMillis(); d.setTime(time); System.out.println(d); }
}
2.3、SimpleDateFormat类(应用)
SimpleDateFormat类概述
SimpleDateFormat是一个具体的类,用于以区域设置敏感的方式格式化和解析日期。
我们重点学习日期格式化和解析
SimpleDateFormat类构造方法
方法名 | 说明 |
---|---|
public SimpleDateFormat() | 构造一个SimpleDateFormat,使用默认模式和日期格式 |
public SimpleDateFormat(String pattern) | 构造一个SimpleDateFormat使用给定的模式和默认的日期格式 |
SimpleDateFormat类的常用方法
格式化(从Date到String)
解析(从String到Date)
示例代码
public class SimpleDateFormatDemo { public static void main(String[] args) throws ParseException {//日期转成字符串Date date = new Date();SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");String s = format.format(date);System.out.println(s);//字符串转换成日期String ss = "2022-08-05 11:29:35";SimpleDateFormat format1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");Date s1 = format1.parse(ss);System.out.println(s1);}
}
2.4、日期工具类案例(应用)
案例需求
定义一个日期工具类(DateUtils),包含两个方法:把日期转换为指定格式的字符串;把字符串解析为指定格式 的日期,然后定义一个测试类(DateDemo),测试日期工具类的方法
代码实现
工具类
public class DateUtils {/* 把日期转为指定格式的字符串 返回值类型:String 参数:Date date, String format */public static String dateToString(Date date, String format){SimpleDateFormat sdf = new SimpleDateFormat(format);String s = sdf.format(date);return s;}/* 把字符串解析为指定格式的日期 返回值类型:Date 参数:String date, String format */public static Date stringToDate(String date,String format) throws ParseException {SimpleDateFormat sdf = new SimpleDateFormat(format);Date strDate = sdf.parse(date);return strDate;}
}
测试类
public class DateDemo { public static void main(String[] args) throws ParseException { //创建日期对象 Date d = new Date(); String s1 = DateUtils.dateToString(d, "yyyy年MM月dd日 HH:mm:ss"); System.out.println(s1); String s2 = DateUtils.dateToString(d, "yyyy年MM月dd日"); System.out.println(s2); String s3 = DateUtils.dateToString(d, "HH:mm:ss"); System.out.println(s3); System.out.println("--------"); String s = "2048-08-09 12:12:12"; Date dd = DateUtils.stringToDate(s, "yyyy-MM-dd HH:mm:ss"); System.out.println(dd); }
}
2.5、Calendar类(应用)
Calendar类概述
Calendar 为特定瞬间与一组日历字段之间的转换提供了一些方法,并为操作日历字段提供了一些方法
Calendar 提供了一个类方法 getInstance 用于获取这种类型的一般有用的对象。
该方法返回一个Calendar 对象。
其日历字段已使用当前日期和时间初始化:Calendar rightNow = Instance();
Calendar类常用方法
方法名 | 说明 |
---|---|
public int get(int fifield) | 返回给定日历字段的值 |
public abstract void add(int fifield, int amount) | 根据日历的规则,将指定的时间量添加或减去给定的日历字段 |
public fifinal void set(int year,int month,int date) | 设置当前日历的年月日 |
示例代码
public class CalendarDemo { public static void main(String[] args) { //获取日历类对象 Calendar c = Instance(); //public int get(int field):返回给定日历字段的值 int year = c.get(Calendar.YEAR); int month = c.get(Calendar.MONTH) + 1; int date = c.get(Calendar.DATE); System.out.println(year + "年" + month + "月" + date + "日"); //public abstract void add(int field, int amount):根据日历的规则,将指定的时 间量添加或减去给定的日历字段 //需求1:3年前的今天 // c.add(Calendar.YEAR,-3); // year = c.get(Calendar.YEAR); // month = c.get(Calendar.MONTH) + 1; // date = c.get(Calendar.DATE); // System.out.println(year + "年" + month + "月" + date + "日"); //需求2:10年后的10天前 // c.add(Calendar.YEAR,10); // c.add(Calendar.DATE,-10); // year = c.get(Calendar.YEAR); // month = c.get(Calendar.MONTH) + 1; // date = c.get(Calendar.DATE); // System.out.println(year + "年" + month + "月" + date + "日"); //public final void set(int year,int month,int date):设置当前日历的年月日 c.set(2050,10,10); //表示2050年11月14日year = c.get(Calendar.YEAR); month = c.get(Calendar.MONTH) + 1; date = c.get(Calendar.DATE); System.out.println(year + "年" + month + "月" + date + "日"); }
}
案例需求
获取任意一年的二月有多少天
代码实现
public class CalendarTest { public static void main(String[] args) {//键盘录入任意的年份Scanner scan = new Scanner(System.in);System.out.print("输入年份:");int year = Int();//设置日历对象的年、月、日Calendar c = Instance();c.set(year,2,1);//月份数字是2表示是3月份//3月1日往前推一天,就是2月的最后一天c.add(Calendar.DATE,-1);System.out.println(year+"年的二月份有"(Calendar.DATE)+"天");}
}
异常的概述
异常就是程序出现了不正常的情况
异常的体系结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xMbhDphm-1660040562540)(D:个人资料java学习问题及笔记java常用类、集合、IOassets1659930747730.png)]
如果程序出现了问题,我们没有做任何处理,最终JVM 会做默认的处理,处理方式有如下两个步骤:
把异常的名称,错误原因及异常出现的位置等信息输出在了控制台
程序停止执行
格式:
try {可能出现异常的代码;
} catch(异常类名 变量名) { 异常的处理代码;
}
执行流程
程序从 try 里面的代码开始执行
出现异常,就会跳转到对应的 catch 里面去执行
执行完毕之后,程序还可以继续往下执行
示例代码
public class ExceptionDemo01 { public static void main(String[] args) { System.out.println("开始"); method(); System.out.println("结束"); }public static void method() { try {int[] arr = {1, 2, 3}; System.out.println(arr[3]); System.out.println("这里能够访问到吗"); } catch (ArrayIndexOutOfBoundsException e) { // System.out.println("你访问的数组索引不存在,请回去修改为正确的索引"); e.printStackTrace(); } }
}
常用方法:
方法名 | 说明 |
---|---|
public String getMessage() | 返回此 throwable 的详细消息字符串 |
public String toString() | 返回此可抛出的简短描述 |
public void printStackTrace() | 把异常的错误信息输出在控制台 |
示例代码:
public class ExceptionDemo02 { public static void main(String[] args) { System.out.println("开始"); method(); System.out.println("结束"); }public static void method() { try {int[] arr = {1, 2, 3}; System.out.println(arr[3]); //new ArrayIndexOutOfBoundsException(); System.out.println("这里能够访问到吗"); } catch (ArrayIndexOutOfBoundsException e) { //new ArrayIndexOutOfBoundsException(); // e.printStackTrace(); //public String getMessage():返回此 throwable 的详细消息字符串 // System.out.Message()); //Index 3 out of bounds for length 3 //public String toString():返回此可抛出的简短描述 // System.out.String()); //java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3//public void printStackTrace():把异常的错误信息输出在控制台 e.printStackTrace(); // java.lang.ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3 // at com.itheima_hod(ExceptionDemo02.java:18) // at com.itheima_02.ExceptionDemo02.main(ExceptionDemo02.java:11) } }
}
编译时异常
都是Exception类及其子类
必须显式处理,否则程序就会发生错误,无法通过编译
运行时异常
都是RuntimeException类及其子类
无需显示处理,也可以和编译时异常一样处理
格式:
public void 方法() throws 异常类名 {
}
示例:
/*throws 异常类名;这个格式是跟在方法的括号后面的*/
public class ExceptionDemo {public static void main(String[] args) {System.out.println("开始");
// method();try {method2();}catch (ParseException e) {e.printStackTrace();}System.out.println("结束");}//编译时异常public static void method2() throws ParseException {String s = "2048-08-09";SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");Date d = sdf.parse(s);System.out.println(d);}//运行时异常public static void method() throws ArrayIndexOutOfBoundsException {int[] arr = {1, 2, 3};System.out.println(arr[3]);}
}
注意事项
这个throws格式是跟在方法的括号后面的
编译时异常必须要进行处理,两种处理方案:try…catch …或者 throws,如果采用 throws 这种方案, 将来谁调用谁处理
运行时异常可以不处理,出现问题后,需要我们回来修改代码
自定义异常类
public class ScoreException extends Exception {public ScoreException() {}public ScoreException(String message) {super(message);}
}
老师类
public class Teacher {public void checkScore(int score) throws ScoreException {if(score<0 || score>100) {//throw new ScoreException();throw new ScoreException("你给的分数有误,分数应该在0-100之间");} else {System.out.println("成绩正常");}}
}
测试类
public class Demo {public static void main(String[] args) {Scanner sc = new Scanner(System.in);System.out.println("请输入分数:");int score = sc.nextInt();Teacher t = new Teacher();try {t.checkScore(score);} catch (ScoreException e) {e.printStackTrace();}}
}
集合类的特点
提供一种存储空间可变的存储模型,存储的数据容量可以随时发生改变
集合类的体系图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FxeYgDCW-1660040562542)(D:个人资料java学习问题及笔记java常用类、集合、IOassets1659939022023.png)]
Collection集合概述
是单例集合的顶层接口,它表示一组对象,这些对象也称为Collection的元素
JDK 不提供此接口的任何直接实现,它提供更具体的子接口(如Set和List)实现
Collection集合基本使用
/*创建Collection集合的对象多态的方式ArrayList()*/
public class CollectionDemo01 {public static void main(String[] args) {//创建Collection集合的对象Collection<String> c = new ArrayList<String>();//添加元素:boolean add(E e)c.add("hello");c.add("world");c.add("java");//输出集合对象System.out.println(c);}
}
方法名 | 说明 |
---|---|
boolean add(E e) | 添加元素 |
boolean remove(Object o) | 从集合中移除指定的元素 |
void clear() | 清空集合中的元素 |
boolean contains(Object o) | 判断集合中是否存在指定的元素 |
boolean isEmpty() | 判断集合是否为空 |
int size() | 集合的长度,也就是集合中元素的个数 |
迭代器的介绍
迭代器,集合的专用遍历方式
Iterator iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到
迭代器是通过集合的iterator()方法得到的,所以我们说它是依赖于集合而存在的
Collection集合的遍历
/*Iterator:迭代器,集合的专用遍历方式Iterator<E> iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到迭代器是通过集合的iterator()方法得到的,所以我们说它是依赖于集合而存在的Iterator中的常用方法E next():返回迭代中的下一个元素boolean hasNext():如果迭代具有更多元素,则返回 true*/
public class IteratorDemo01 {public static void main(String[] args) {//创建集合对象Collection<String> c = new ArrayList<String>();//添加元素c.add("hello");c.add("world");c.add("java");//Iterator<E> iterator():返回此集合中元素的迭代器,通过集合的iterator()方法得到Iterator<String> it = c.iterator(); //用while循环改进判断while (it.hasNext()) {//System.out.());String s = it.next();System.out.println(s);}}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6xV60acs-1660040562543)(D:个人资料java学习问题及笔记java常用类、集合、IOassets1659940057849.png)]
Iterator< String > it = c.iterator();把集合中的数据复制了一份给迭代器对象。while这块首先有个东西指向了这个元素hello,然后it.hasNext();先判断此处是否有元素,有就执行String s = it.next();把当前的hello这个值拿出来给s,然后它本身再指向下一个地址。一直重复,直到指向的位置没有元素就结束。
案例需求
创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合
代码实现
学生类
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;}
}
测试类
/*需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合思路:1:定义学生类2:创建Collection集合对象3:创建学生对象4:把学生添加到集合5:遍历集合(迭代器方式)*/
public class CollectionDemo {public static void main(String[] args) {//创建Collection集合对象Collection<Student> c = new ArrayList<Student>();//创建学生对象Student s1 = new Student("林青霞", 30);Student s2 = new Student("张曼玉", 35);Student s3 = new Student("王祖贤", 33);//把学生添加到集合c.add(s1);c.add(s2);c.add(s3);//遍历集合(迭代器方式)//方式一:Iterator<Student> it = c.iterator();while (it.hasNext()) {Student s = it.next();System.out.Name() + "," + s.getAge());}//方式二:for (Student student : c) {System.out.Name()+ "," + Age());}}
}
List集合概述
有序集合(也称为序列),用户可以精确控制列表中每个元素的插入位置。用户可以通过整数索引访问元素,并搜索列表中的元素
与Set集合不同,列表通常允许重复的元素
List集合特点
有索引
可以存储重复元素
元素存取有序
方法名 | 描述 |
---|---|
void add(int index,E element) | 在此集合中的指定位置插入指定的元素 |
E remove(int index) | 删除指定索引处的元素,返回被删除的元素 |
E set(int index,E element) | 修改指定索引处的元素,返回被修改的元素 |
E get(int index) | 返回指定索引处的元素 |
案例需求
代码实现
学生类
代码同1.6学生类
测试类同1.6测试类 把Collection改成List即可
出现的原因
迭代器遍历的过程中,通过集合对象修改了集合中的元素,造成了迭代器获取元素中判断预期修改值和实际 修改值不一致,则会出现:ConcurrentModifificationException
解决的方案
用for循环遍历,然后用集合对象做对应的操作即可
示例代码
public class ListDemo { public static void main(String[] args) { //创建集合对象 List<String> list = new ArrayList<String>(); //添加元素 list.add("hello"); list.add("world"); list.add("java"); //遍历集合,得到每一个元素,看有没有"world"这个元素,如果有,我就添加一 个"javaee"元素,请写代码实现 //报错:ConcurrentModifificationException/*Iterator<String> it = list.iterator(); while (it.hasNext()) { String s = it.next(); if(s.equals("world")) { list.add("javaee"); } }*/for(int i=0; i<list.size(); i++) { String s = (i);if(s.equals("world")) { list.add("javaee"); } }//输出集合对象 System.out.println(list); }
}
ListIterator介绍
通过List集合的listIterator()方法得到,所以说它是List集合特有的迭代器
用于允许程序员沿任一方向遍历的列表迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置
示例代码
/*ListIterator:列表迭代器通过List集合的listIterator()方法得到,所以说它是List集合特有的迭代器用于允许程序员沿任一方向遍历列表的列表的迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置ListIterator中的常用方法E next():返回迭代中的下一个元素boolean hasNext():如果迭代具有更多元素,则返回 trueE previous():返回列表中的上一个元素boolean hasPrevious():如果此列表迭代器在相反方向遍历列表时具有更多元素,则返回 truevoid add(E e):将指定的元素插入列表*/
public class ListIteratorDemo {public static void main(String[] args) {//创建集合对象List<String> list = new ArrayList<String>();//添加元素list.add("hello");list.add("world");list.add("java");//输出集合对象
// System.out.println(list);//迭代器的方式遍历ListIterator<String> it = list.listIterator();while (it.hasNext()) {String s = it.next();if (s.equals("world")){it.add("javaee");//若为list.add同样会报错}//System.out.println(s);}System.out.println(list);}
}
定义格式
for(元素数据类型 变量名 : 数组/集合对象名) { 循环体;
}
示例代码
/*增强for:简化数组和Collection集合的遍历实现Iterable接口的类允许其对象成为增强型 for语句的目标它是JDK5之后出现的,其内部原理是一个Iterator迭代器格式:for(元素数据类型 变量名 : 数组或者Collection集合) {//在此处使用变量即可,该变量就是元素}*/
public class ForDemo {public static void main(String[] args) {int[] arr = {1,2,3,4,5};for(int i : arr) {System.out.println(i);}System.out.println("--------");String[] strArray = {"hello","world","java"};for(String s : strArray) {System.out.println(s);}System.out.println("--------");List<String> list = new ArrayList<String>();list.add("hello");list.add("world");list.add("java");for(String s : list) {System.out.println(s);}System.out.println("--------");//内部原理是一个Iterator迭代器/*for(String s : list) {if(s.equals("world")) {list.add("javaee"); //ConcurrentModificationException}}*/}
}
案例需求
创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合
代码实现
学生类 同上
测试类
/*需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合思路:1:定义学生类2:创建List集合对象3:创建学生对象4:把学生添加到集合5:遍历集合迭代器:集合特有的遍历方式普通for:带有索引的遍历方式增强for:最方便的遍历方式*/
public class ListDemo {public static void main(String[] args) {//创建List集合对象List<Student> list = new ArrayList<Student>();//创建学生对象Student s1 = new Student("林青霞", 30);Student s2 = new Student("张曼玉", 35);Student s3 = new Student("王祖贤", 33);//把学生添加到集合list.add(s1);list.add(s2);list.add(s3);//迭代器:集合特有的遍历方式Iterator<Student> it = list.iterator();while (it.hasNext()) {Student s = it.next();System.out.Name()+","Age());}System.out.println("--------");//普通for:带有索引的遍历方式for(int i=0; i<list.size(); i++) {Student s = (i);System.out.Name()+","Age());}System.out.println("--------");//增强for:最方便的遍历方式for(Student s : list) {System.out.Name()+","Age());}}
}
数据结构是计算机存储、组织数据的方式。是指相互之间存在一种或多种特定关系的数据元素的集合
通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率
栈结构
栈是一种数据先进后出的模型,如下图,进去的时候是A先进,出来的时候是D先出
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c6ZoKKYZ-1660040562543)(D:个人资料java学习问题及笔记java常用类、集合、IOassets1659944725578.png)]
队列结构
队列是一种数据先进先出的模型
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LEqItunz-1660040562544)(D:个人资料java学习问题及笔记java常用类、集合、IOassets1659944901880.png)]
数组结构 :是一种查询快,增删慢的模型
链表结构:查询慢、增删快
链表可分为单向链表和双向链表。
一个单向链表包含两个值: 当前节点的值和一个指向下一个节点的链接。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f0UiuKji-1660040562544)(D:个人资料java学习问题及笔记java常用类、集合、IOassets1659946756467.png)]
一个双向链表有三个整数值: 数值、向后的节点链接、向前的节点链接。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VB132Npp-1660040562544)(D:个人资料java学习问题及笔记java常用类、集合、IOassets1659946776913.png)]
ArrayList集合
LinkedList集合
案例需求
代码实现
/*需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合思路:1:定义学生类2:创建ArrayList集合对象3:创建学生对象4:把学生添加到集合5:遍历集合迭代器:集合特有的遍历方式普通for:带有索引的遍历方式增强for:最方便的遍历方式*/
public class ArrayListDemo {public static void main(String[] args) {//创建ArrayList集合对象ArrayList<Student> array = new ArrayList<Student>();//创建学生对象Student s1 = new Student("林青霞", 30);Student s2 = new Student("张曼玉", 35);Student s3 = new Student("王祖贤", 33);//把学生添加到集合array.add(s1);array.add(s2);array.add(s3);//迭代器:集合特有的遍历方式Iterator<Student> it = array.iterator();while (it.hasNext()) {Student s = it.next();System.out.Name() + "," + s.getAge());}System.out.println("--------");//普通for:带有索引的遍历方式for(int i=0; i<array.size(); i++) {Student s = (i);System.out.Name() + "," + s.getAge());}System.out.println("--------");//增强for:最方便的遍历方式for(Student s : array) {System.out.Name() + "," + s.getAge());}}
}
特有方法
方法 | 描述 |
---|---|
public void addFirst(E e) | 元素添加到头部。 |
public void addLast(E e) | 元素添加到尾部。 |
public E removeFirst() | 删除并返回第一个元素。 |
public E removeLast() | 删除并返回最后一个元素。 |
public E getFirst() | 返回第一个元素。 |
public E getLast() | 返回最后一个元素。 |
Set集合的特点
元素存取无序
没有索引、只能通过迭代器或增强for循环遍历
不能存储重复元素
Set集合的基本使用
/*Set集合特点不包含重复元素的集合没有带索引的方法,所以不能使用普通for循环遍历HashSet:对集合的迭代顺序不作任何保证*/
public class SetDemo {public static void main(String[] args) {//创建集合对象Set<String> set = new HashSet<String>();//添加元素set.add("hello");set.add("world");set.add("java");//不包含重复元素的集合set.add("world");//遍历for(String s : set) {System.out.println(s);}}
}
//结果为:
world
java
hello
哈希值简介
如何获取哈希值
哈希值的特点
同一个对象多次调用hashCode()方法返回的哈希值是相同的
默认情况下,不同对象的哈希值是不同的。而重写hashCode()方法,可以实现让不同对象的哈希值相同
获取哈希值的代码
学生类 同上
测试类
/*哈希值:是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值Object类中有一个方法可以获取对象的哈希值public int hashCode():返回对象的哈希码值*/
public class HashDemo {public static void main(String[] args) {//创建学生对象Student s1 = new Student("林青霞",30);//同一个对象多次调用hashCode()方法返回的哈希值是相同的System.out.println(s1.hashCode()); //1060830840System.out.println(s1.hashCode()); //1060830840System.out.println("--------");Student s2 = new Student("林青霞",30);//默认情况下,不同对象的哈希值是不相同的//通过方法重写,可以实现不同对象的哈希值是相同的System.out.println(s2.hashCode()); //2137211482System.out.println("--------");System.out.println("hello".hashCode()); //99162322System.out.println("world".hashCode()); //113318802System.out.println("java".hashCode()); //3254818System.out.println("world".hashCode()); //113318802System.out.println("--------");//因为String类重写了hashcode方法,所以有可能导致两个字符串哈希值相同System.out.println("重地".hashCode()); //1179395System.out.println("通话".hashCode()); //1179395}
}
HashSet集合的特点
底层数据结构是哈希表
对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致
没有带索引的方法,所以不能使用普通for循环遍历
由于是Set集合,所以是不包含重复元素的集合
HashSet集合的基本使用
/*HashSet集合特点1:底层数据结构是哈希表2:对集合的迭代顺序不作任何保证,也就是说不保证存储和取出的元素顺序一致3:没有带索引的方法,所以不能使用普通for循环遍历4:由于是Set集合,所以是不包含重复元素的集合*/
public class HashSetDemo01 {public static void main(String[] args) {//创建集合对象HashSet<String> hs = new HashSet<String>();//添加元素hs.add("hello");hs.add("world");hs.add("java");hs.add("world");//遍历for(String s : hs) {System.out.println(s);}}
}
HashSet集合保证元素唯一性的原理
第一步:根据对象的哈希值计算存储位置
第二步:当前元素的元素和已经存在的元素比较哈希值
第三步:通过equals()方法比较两个元素的内容
HashSet集合保证元素唯一性的图解
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ABZCJ5Qe-1660040562545)(D:个人资料java学习问题及笔记java常用类、集合、IOassets1659951079652.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TnP7bKmF-1660040562546)(D:个人资料java学习问题及笔记java常用类、集合、IOassets1660008159272.png)]
存储过程:HashSet默认初始容量为16。首先计算一个字符串在该HashSet的存储位置:即除以16取余。可以看到,hello、world、java取余都是2,首先存储hello,在2位置处没有元素,因此hello直接存储进去,接着存储world,发现在2位置处有元素,将world与2位置的所有元素进行对比,首先比较哈希值,发现哈希值不同则存储进去,java存储同理。接着再次在2位置存储world,发现2位置处已有元素,比较哈希值,发现有与world哈希值相同的元素,再比较对象的内容,发现内容也相同,尤其判断是重复元素,不予存储。
案例需求
创建一个存储学生对象的集合,存储多个学生对象,使用程序实现在控制台遍历该集合
要求:学生对象的成员变量值相同,我们就认为是同一个对象
代码实现
学生类
public class Student {private String name;private int age;public Student() {}//此处省略get、set方法@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;}
}
测试类
/*需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合要求:学生对象的成员变量值相同,我们就认为是同一个对象思路:1:定义学生类2:创建HashSet集合对象3:创建学生对象4:把学生添加到集合5:遍历集合(增强for)*/
public class HashSetDemo02 {public static void main(String[] args) {//创建HashSet集合对象HashSet<Student> hs = new HashSet<Student>();//创建学生对象Student s1 = new Student("林青霞", 30);Student s2 = new Student("张曼玉", 35);Student s3 = new Student("王祖贤", 33);Student s4 = new Student("王祖贤", 33);//把学生添加到集合hs.add(s1);hs.add(s2);hs.add(s3);hs.add(s4);//遍历集合(增强for)for (Student s : hs) {System.out.Name() + "," + s.getAge());}HashSet<String> sites = new HashSet<String>();sites.add("Google");sites.add("Runoob");sites.add("Taobao");sites.add("Zhihu");sites.add("Runoob"); // 重复的元素不会被添加System.out.println(sites);}
}
注:学生类中必须重写 equals和hashCode方法,否则测试时s4同样会被写进hs中,因为HashSet本身无法辨别以student创建的对象元素是否相同。若student类不重写两个方法,结果集hs会有两个“王祖贤”,而sites里却只有一个"Runoob"。
LinkedHashSet集合特点
哈希表和链表实现的Set接口,具有可预测的迭代次序
由链表保证元素有序,也就是说元素的存储和取出顺序是一致的
由哈希表保证元素唯一,也就是说没有重复的元素
LinkedHashSet集合基本使用
/*LinkedHashSet集合特点1:哈希表和链表实现的Set接口,具有可预测的迭代次序2:由链表保证元素有序,也就是说元素的存储和取出顺序是一致的3:由哈希表保证元素唯一,也就是说没有重复的元素*/
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);}}
}
TreeSet集合概述
元素有序,可以按照一定的规则进行排序,具体排序方式取决于构造方法
TreeSet():根据其元素的自然排序(数字从小到大字母从a到z)进行排序
TreeSet(Comparator comparator) :根据指定的比较器进行排序
没有带索引的方法,所以不能使用普通for循环遍历
由于是Set集合,所以不包含重复元素的集合
TreeSet集合基本使用
public class TreeSetDemo01 {public static void main(String[] args) {//创建集合对象TreeSet<Integer> ts = new TreeSet<Integer>();//添加元素ts.add(10);ts.add(40);ts.add(30);ts.add(50);ts.add(20);ts.add(30);//遍历集合for(Integer i : ts) {System.out.println(i);}}
}
// 结果:10 20 30 40 50 从小到大排列,并且不包含重复元素
案例需求
存储学生对象并遍历,创建TreeSet集合使用无参构造方法
要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
实现步骤
用TreeSet集合存储自定义对象,无参构造方法使用的是自然排序对元素进行排序的
自然排序,就是让元素所属的类实现Comparable接口,重写compareTo(T o)方法
重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
代码实现
学生类
public class Student implements Comparable<Student> {private String name;private int age;// 省略getset有参无参构造@Overridepublic int compareTo(Student s) {
// return 0; 0表示两者相等,则认为是重复数据不天剑
// return 1; 1是正数,也可以是任意正数,表示后者比前者大,存储数据按照从前往后排列
// return -1; -1也可以是任意负数,表示后者比前者小,存储数据按照从后往前排列//按照年龄从小到大排序//System.out.println("this:"+this.age+","+"s:"+s.age);int num = this.age - s.age;
// int num = s.age - this.age;//年龄相同时,按照姓名的字母顺序排序int num2 = num==0?this.namepareTo(s.name):num;return num2;}
}
测试类:
/*存储学生对象并遍历,创建集合使用无参构造方法要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序*/
public class TreeSetDemo02 {public static void main(String[] args) {//创建集合对象TreeSet<Student> ts = new TreeSet<Student>();//创建学生对象Student s1 = new Student("xishi", 29);Student s2 = new Student("wangzhaojun", 28);Student s3 = new Student("diaochan", 30);Student s4 = new Student("yangyuhuan", 33);Student s5 = new Student("linqingxia",33);Student s6 = new Student("linqingxia",33);//把学生添加到集合ts.add(s1);ts.add(s2);ts.add(s3);ts.add(s4);ts.add(s5);ts.add(s6);//遍历集合for (Student s : ts) {System.out.Name() + "," + s.getAge());}}
}
注:int num = this.age - s.age中,this指的是每次新输入的年龄,s指的上一次做比较的年龄。
TreeSet比较流程:
(1)在第一次输入(“xishi”, 29)后,this.age=s.age=29,此时num=0,则执行this.namepareTo(s.name),可得num2=0,保存(“xishi”, 29)数据;
(2)第二次输入(“wangzhaojun”, 28),this.age=28,s.age=29,此时num=-1,(“wangzhaojun”, 28)存储在(“xishi”, 29)前面
(3)第三次输入(“diaochan”, 30),this.age=30,s.age=29,此时num=1,(“diaochan”, 30)放到(“xishi”, 29)后面。
(4)第四次输入(“yangyuhuan”, 33),this.age=33,s.age=29,此时num=4,放到(“xishi”, 29)后面。但此时(“xishi”, 29)后已经有(“diaochan”, 30),因此两者要比较,此时s.age=30,与this.age=33比较,num=3,因此(“yangyuhuan”, 33)放到(“diaochan”, 30)后面。
(5)第五次输入(“linqingxia”,33),this.age=33,s从最开始取值,首先s.age=29,num=4,放(“xishi”, 29)后面;再s.age=30,num=3,放(“diaochan”, 30)后面;再s.age=33,比较名字,放(“yangyuhuan”, 33)前面。
(6)第六次输入(“linqingxia”,33),this.age=33,首先s.age=29,num=4,放(“xishi”, 29)后面;再s.age=30,num=3,放(“diaochan”, 30)后面;再s.age=33,比较名字,与前面保存的数据重复,不予保存。
案例需求
存储学生对象并遍历,创建TreeSet集合使用带参构造方法
要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
实现步骤
用TreeSet集合存储自定义对象,带参构造方法使用的是比较器排序对元素进行排序的
比较器排序,就是让集合构造方法接收Comparator的实现类对象,重写compare(T o1,T o2)方法
重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
代码实现
学生类
public class Student {private String name;private int age;//省略无参/有参/get/set方法
}
测试类
public class TreeSetDemo {public static void main(String[] args) {//创建集合对象TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {@Overridepublic int compare(Student s1, Student s2) {//this.age - s.age//s1,s2int num = s1.getAge() - s2.getAge();int num2 = num == 0 ? s1.getName()Name()) : num;return num2;}});//创建学生对象Student s1 = new Student("xishi", 29);Student s2 = new Student("wangzhaojun", 28);Student s3 = new Student("diaochan", 30);Student s4 = new Student("yangyuhuan", 33);Student s5 = new Student("linqingxia",33);Student s6 = new Student("linqingxia",33);//把学生添加到集合ts.add(s1);ts.add(s2);ts.add(s3);ts.add(s4);ts.add(s5);ts.add(s6);//遍历集合for (Student s : ts) {System.out.Name() + "," + s.getAge());}}
}
/*需求:编写一个程序,获取10个1-20之间的随机数,要求随机数不能重复,并在控制台输出思路:1:创建Set集合对象2:创建随机数对象3:判断集合的长度是不是小于10是:产生一个随机数,添加到集合回到3继续4:遍历集合*/
public class SetDemo {public static void main(String[] args) {//创建Set集合对象
// Set<Integer> set = new HashSet<Integer>();Set<Integer> set = new TreeSet<Integer>();//创建随机数对象Random r = new Random();//判断集合的长度是不是小于10while (set.size()<10) {//产生一个随机数,添加到集合int number = r.nextInt(20) + 1;set.add(number);}//遍历集合for(Integer i : set) {System.out.println(i);}}
}
参考:Java中的包装类、泛型
泛型概述
是JDK5中引入的特性,它提供了编译时类型安全检测机制,该机制允许在编译时检测到非法的类型。它的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,然后在使用/调用时传入具体的类型。这种参数类型可以用在类、方法和接口中,分别被称为泛型类、泛型方法、泛型接口
泛型定义格式 : 泛型指的是在类定义时不明确类型,而在使用时明确类型。定义泛型使用"<>"操作符。
<类型>:指定一种类型的格式。这里的类型可以看成是形参
<类型1,类型2…>:指定多种类型的格式,多种类型之间用逗号隔开。这里的类型可以看成是形参
将来具体调用时候给定的类型可以看成是实参,并且实参的类型只能是引用数据类型
泛型的好处
把运行时期的问题提前到了编译期间
避免了强制类型转换
定义格式
修饰符 class 类名<类型> { }
示例代码
泛型类
public class Generic<T> {private T t;public T getT() {return t;}public void setT(T t) {this.t = t;}
}
测试类
public class GenericDemo {public static void main(String[] args) {Student s = new Student();s.setName("林青霞");System.out.Name());Teacher t = new Teacher();t.setAge(30);
// t.setAge("30");System.out.Age());System.out.println("--------");Generic<String> g1 = new Generic<String>();g1.setT("林青霞");System.out.T());Generic<Integer> g2 = new Generic<Integer>();g2.setT(30);System.out.T());Generic<Boolean> g3 = new Generic<Boolean>();g3.setT(true);System.out.T());}
}
定义格式
修饰符 <类型> 返回值类型 方法名(类型 变量名) { }
public class Generic {public <T> void show(T t) {System.out.println(t);}
}
public class GenericDemo {public static void main(String[] args) {Generic g = new Generic();g.show("林青霞");g.show(30);g.show(true);g.show(12.34);}
}
定义格式
修饰符 interface 接口名<类型> { }
public interface Generic<T> {void show(T t);
}
一旦一个接口使用泛型声明,子类在实现接口时就有两种选择
a. 继续保留泛型
public class GenericImpl<T> implements Generic<T> {@Overridepublic void show(T t) {System.out.println(t);}
}
b. 子类明确当前类型
public class GenericImpl02 implements Generic<String> {@Overridepublic void show(String s) {System.out.println(s);}
}
测试:
public class GenericDemo {public static void main(String[] args) {Generic<String> g1 = new GenericImpl<String>();g1.show("林青霞");Generic<Integer> g2 = new GenericImpl<Integer>();g2.show(30);Generic<String> g3 = new GenericImpl02();//此时只能接受String类型g3.show("fdfasf");}
}
本文发布于:2024-01-27 18:41:10,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/17063520701951.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |