目录
包装类
一、包装类: Java是一个面向对象的编程语言,但是Java中的八种基本数据类型却是不面向对象的,为了使用方便和解决这个不足,在设计类时为每个基本数据类型设计了一个对应的类进行代表,这样八种基本数据类型对应的类统称为包装类,包装类均位于java.lang
包。
二、
基本类型 | 对应的包装类(位于java.lang包中) |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Charater |
boolean | Boolean |
三、装箱:把基本类型的数据包装到包装类中 即基本类型的数据转换为包装类
四、构造方法:
Integer(int value)
:构造一个新分配的Integer
对象 他表示指定的int
值Integer(String s)
:构造一个新分配的Integer
对象 他表示String
参数所指示的int
值
注意:传递的字符串必须是基本类型的字符串 否则会抛出异常 例如:"100"正确 "a"会报错
public class BaoZhuangLei {
public static void main(String[] args) {
Integer in1 = new Integer(1);
System.out.println(in1);//1 重写了toString方法
Integer in2 = new Integer("1");
System.out.println(in2);//1
}
}
五、静态方法:
static Integer valueOf(int i)
:返回一个表示指定的int
值的Integer
实例static Integer valueOf(String s)
:返回保存指定的String
的值的Integer
对象
public class BaoZhuangLei {
public static void main(String[] args) {
Integer in3 = Integer.valueOf(1);
System.out.println(in3);//1
Integer in4 = Integer.valueOf("1");
System.out.println(in4);//1
/*
* Integer in5 = Integer.valueOf("a");
* System.out.println(in5);//NumberFormatException数字格式化异常
*/
}
}
六、拆箱:在包装类中取出基本类型的数据 即包装类转换为基本类型的数据
public class BaoZhuangLei {
public static void main(String[] args) {
int i = in1.intValue();
System.out.println(i);//1
}
}
七、成员方法:int intValue()
:以int
类型返回该Integer
的值
八、自动装箱与拆箱:基本类型的数据和包装类之间可以自动的相互转换
public class BaoZhuangLei {
public static void main(String[] args) {
System.out.println("自动装箱与拆箱:==================================================");
//自动装箱:直接把int类型的整数赋值包装类
Integer in = 1;//相当于Integer in = new Integer(1);
//自动拆箱:in是包装类 无法直接参与运算 可以自动转换为基本数据类型 再进行计算
in = in + 2;//in + 2相当于in.inValue() + 2 = 3 然后in = in.inValue() + 2 = 3又是一个自动装箱
ArrayList<Integer> list = new ArrayList();
//ArrayList集合无法直接存储整数 可以存储Integer包装类
list.add(1);//隐含了自动装箱 list.add(new Integer(1));
int a =list.get(0);//隐含了自动拆箱 list.get(0).inValue();
}
}
九、基本类型转换为字符串类型
基本类型的值 + “”
最简单的方法- 包装类的静态方法
toString(参数)
不是Object类的toString(),而是Object类的toString()的重载形式 - String类的静态方法valueOf(参数):
static String valueOf(int i)
:返回int
参数的字符串表示形式
public class BaoZhuangLei {
public static void main(String[] args) {
System.out.println("基本类型转换为字符串:===============================");
//方式一
int i1 = 100;
String s1 = i1 + "";
System.out.println(s1 + 200);//100200 字符串相加时拼接
//方式二
String s2 = Integer.toString(100);
System.out.println(s2 + 200);//100200
//方式三
String s3 = String.valueOf(100);
System.out.println(s3 + 200);//100200
}
}
十、字符串转换为基本类型:使用包装类的静态方法:parseXXX("字符串类型的数字(如果写“A” 字符串类型的字母 会报错)");
例如:
Integer类:static int parseInt(String s)
Double类:static double parseDouble(String s)
import java.util.ArrayList;
public class BaoZhuangLei {
public static void main(String[] args) {
int m = Integer.parseInt(s1);
System.out.println(m - 10);//90
}
}
java.util.Calendar日历类
一、java.util.Calendar
类:日历类 里边提供了很多操作日历字段的方法(YEAR MONTH DAY_OF_MONTH HOUR)
二、Calendar类是一个抽象类 无法直接创建对象使用 里边有一个静态方法叫getInstance()
,该方法返回了Calendar类的子类对象
三、getInstance()
用法:static Calendar getInstance()
:使用默认时区和语言环境获得一个日历
四、Calendar
类的常用成员方法:
public int get(int field)
:返回给定日历字段的值
/*
* 参数:传递指定的日历字段(YEAR MONTH……)
* 返回值:日历字段代表的具体值 例如:你给我的是YEAR就返回2019
*/
private static void demo01() {
//使用getInstance方法获取Calendar对象
Calendar c = Calendar.getInstance();//多态
System.out.println(c);//输出的不是地址值 说明getInstance方法被重写了
int year = c.get(Calendar.YEAR);
System.out.println(year);//2019
int month = c.get(Calendar.MONTH);
System.out.println(month);//西方的月份0-11 东方的月份1-12 今天是北京时间8月14 而打印的是西方的月份7月
int date = c.get(Calendar.DAY_OF_MONTH);
System.out.println(date);//14
int day = c.get(Calendar.DATE);
System.out.println(day);//14
}
public void set(int field,int value)
:将给定的日历字段设置为给定值
/*
* 参数:
* int field:传递指定的日历字段(YEAR MONTH……)
* int value:给指定字段设置的值
*/
private static void demo02() {
//使用getInstance方法获取Calendar对象
Calendar c = Calendar.getInstance();
//设置年为9999年
c.set(Calendar.YEAR, 9999);
int year = c.get(Calendar.YEAR);
System.out.println(year);//9999
//设置月为9月
c.set(Calendar.MONTH, 9);
int month = c.get(Calendar.MONTH);
System.out.println(month);//9
//设置日为9日
c.set(Calendar.DATE, 9);
int date = c.get(Calendar.DAY_OF_MONTH);
System.out.println(date);//9
//设置日为9日
c.set(Calendar.DAY_OF_MONTH, 9);
int day = c.get(Calendar.DATE);
System.out.println(day);
//可以同时设置年月日
c.set(8888, 8, 8);
int year2 = c.get(Calendar.YEAR);
System.out.println(year2);//8888
int month2 = c.get(Calendar.MONTH);
System.out.println(month2);//8
int date2 = c.get(Calendar.DAY_OF_MONTH);
System.out.println(date2);//8
int day2 = c.get(Calendar.DATE);
System.out.println(day2);//8
}
public obstract void add(int field,int amount)
:根据日历的规则 为给定的日历字段添加或减去指定的时间量
/*
* public obstract void add(int field,int amount):把指定的字段增加或减少指定的值
* 参数:
* int field:传递指定的日历字段(YEAR MONTH……)
* int value:给指定字段设置的值 正数:增加 负数:减少
*/
private static void demo03() {
//使用getInstance方法获取Calendar对象
Calendar c = Calendar.getInstance();
//增加两年
c.add(Calendar.YEAR, 2);
int year = c.get(Calendar.YEAR);
System.out.println(year);//2021
//减少三个月
c.add(Calendar.MONTH, -3);
int month = c.get(Calendar.MONTH);
System.out.println(month);//4 西方月份7-3=4
}
public Date getTime()
:返回一个表示此Calendar
时间值(从历元到现在的毫秒偏移量)的Date对象
//public Date getTime():把日历对象转换为日期对象
private static void demo04() {
//使用getInstance方法获取Calendar对象
Calendar c = Calendar.getInstance();
Date date = c.getTime();
System.out.println(date);//Wed Aug 14 12:45:48 CST 2019
}
五、成员方法的参数:
- int field:日历类的字段 可以使用Calendar类的静态变量获取
public static final int YEAR = 1;
年public static final int MONTH = 2;
月public static final int DATE = 5;
月中的某一天public static final int DAY_OF_MONTH = 5;
月中的某一天public static final int HOUR = 10;
时public static final int MINUTE = 12;
分public static final int SECOND = 13;
秒
import java.util.Calendar;
import java.util.Date;
public class Calendar2 {
public static void main(String[] args) {
demo01();
demo02();
demo03();
demo04();
}
}
Date类
一、java.util.Date
:表示时间和日期的类
二、Date类:表示特定的瞬间 精确到毫秒
- 毫秒:千分之一秒 1000ms=1s
- 特定的瞬间:一个时间点 一刹那时间 一瞬间
- 毫秒值的作用:可以对时间和日期进行计算 如:计算2099-01-03到2088-01-01有多少天:先把日期转换为毫秒进行计算 计算完毕再把毫秒转换为日期
三、把日期转换为毫秒:
- 当前日期:
2088-01-01
- 时间原点(0ms):
1970-01-01-00:00:00
(英国格林威治) - 计算当前日期到时间原点之间一共经历了多少毫秒(long类型)
- 把毫秒转换为日期:
1天 = 24 * 60 * 60 = 86400s = 86400000ms
- 注意:中国属于东八区 会把时间增加8个小时 所以时间原点为:
1970-01-01-08:00:00
public class Date {
public static void main(String[] args) {
System.out.println(System.currentTimeMillis());//1565623684373
//获取当前系统时间到时间原点经历了多少毫秒
}
}
四、Date类中的方法练习
import java.util.Date;
public class Date2 {
public static void main(String[] args) {
demo01();
demo02();
demo03();
}
/*
* Date类的空参数构造方法
* Date()获取当前系统的日期和时间
*
*/
private static void demo01() {
Date date = new Date();
System.out.println(date);//打印当前时间 CST指北京时间
}
/*
* Date类的带参数构造方法
* Date(long date):传递毫秒值 把毫秒值转换为Date日期
*
*/
private static void demo02() {
Date date = new Date(0L);
System.out.println(date);//输出时间原点
}
/*
* Long getTime():把日期转换为毫秒值 返回时间原点到当前时间的毫秒数 相当于System.currentTimeMillis()方法
*/
private static void demo03() {
Date date = new Date();
long time = date.getTime();
System.out.println(time);//1565623665518
}
}
DateFormat类
一、java.text.DateFormat
:是日期/时间格式化子类的抽象类 父类是Format类
二、作用:
- 格式化:日期转换为文本
- 解析:文本转换为日期
三、成员方法:
String format(Date date)
:按照指定的格式 把date日期格式化为符合格式的字符串
/*
* 使用DateFormat类中的方法format,把日期格式化为文本 使用步骤:
* 1.创建SimpleDateFormat对象 构造方法中传递指定的格式
* 2.调用SimpleDateFormat对象中的方法format 按照构造方法中指定的格式 把Date日期格式化为符合格式的字符串(文本)
*/
public static void demo01() {
//1.创建SimpleDateFormat对象 构造方法中传递指定的格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd天 HH小时mm分ss秒");
//2.调用SimpleDateFormat对象中的方法format 按照构造方法中指定的格式 把Date日期格式化为符合格式的字符串(文本)
//String format(Date date):按照指定的格式 把date日期格式化为符合格式的字符串
Date date = new Date();
String d = sdf.format(date);
System.out.println(date);
System.out.println(d);
}
Date parse(String source)
:把符合格式的字符串解析为date日期
/*
* 使用DateFormat类中的方法parse,把文本解析为日期 使用步骤:
* 1.创建SimpleDateFormat对象 构造方法中传递指定的格式
* 2.调用SimpleDateFormat对象中的方法parse 把符合构造方法中模式的字符串解析为Date日期
* 注意:public Date parse(String source) throws ParseException:如果字符串和构造方法的格式不一样 那么程序就会抛出此异常
* 调用一个抛出了异常的方法 就必须得处理这个异常 要么throws继续抛出这个异常 要么try catch自己处理
*/
private static void demo02() throws ParseException {
//1.创建SimpleDateFormat对象 构造方法中传递指定的格式
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy年MM月dd天 HH小时mm分ss秒");
//2.调用SimpleDateFormat对象中的方法parse 把符合构造方法中模式的字符串解析为Date日期
//Date parse(String source)把符合格式的字符串解析为Date日期
Date date2 = sdf2.parse("2019年08月14天 10小时05分48秒");//方法名如果写做public static void demo02()此处会显示异常
//我们把该异常交给虚拟机处理 将方法改为 private static void demo02() throws ParseException 即可
System.out.println(date2);
}
四、DateFormat类是一个抽象类 无法直接创建对象使用 可以使用DateFormat的子类:java.text.SimpleDateFormat extends DateFormat
五、SimpleDateFormat的构造方法:SimpleDateFormat (String pattern)
:用给定的格式和默认语言环境的日期格式符号构造SimpleDateFormat
- 参数:String pattern:传递指定的格式
- 格式:区分大小写:
y代表年,M代表月,d代表日,H代表时,m代表分,s代表秒。写对应的格式会把替换为对应的日期和时间:"yyyy-MM-dd HH:mm:ss"
注意:格式中的字母不能更改 连接模式的符号可以改变 上述格式也可以写作:
"yyyy年MM月dd天 HH小时mm分ss秒"
import java.text.SimpleDateFormat;//demo01
import java.text.ParseException;//demo02声明异常
import java.util.Date;
public class DateFormat {
public static void main(String[] args) throws ParseException{
demo01();
demo02();//因为main方法调用了demo02 如果不把他改为public static void main(String[] args) throws ParseException依旧会报错
}
}
StringBuilder类
一、String类:
- 字符串是常量 他们的值在创建之后不能更改 字符串的底层是一个被final修饰的数组 他不能改变
- 底层代码:
private final byte[] value;
- 进行字符串相加时 内存中就会有多个字符串 占用空间多 效率低下 例如:String s = “a”+“b”+“c”=“abc”,内存为String s字符串分配的空间如下:
“a” “b” “c”:三个字符串
“a”+“b”=“ab” 一个字符串
“ab”+“c”=“abc” 一个字符串
内存中首先存放"a"“b”“c"三个字符串 然后进行"a” + “b” = “ab” 产生了一个字符串 然后在进行"ab" + “c” = “abc”,又产生了"abc"字符串 共产生5个字符串
二、StringBuilder类:字符串缓冲区 缓冲区可以提高字符串的操作效率 可以将其看作是一个长度可以变化的字符串。底层也是一个数组 但是没有被final修饰 可以改变长度。
- 底层代码:
byte[] value = new byte[16];
StringBuilder默认初始长度为16 - StringBuilder在内存中始终是一个数组 占用空间少 效率高 如果超出了StringBuilder的容量 会自动扩容
- 例如:“a” + “b” + “c” = “abc” 先将"a"放入第0个的位置 再将"b"放入第1个位置 最后将"c"放入第2个位置 就得到了"abc"
三、java.lang.StringBuilder
类:字符串缓冲区 可以提高字符串的效率
- 构造方法:
StringBuilder()
:构造一个不带任何字符的字符串生成器 其初始容量为16个字符
StringBuilder(String str)
:构造一个字符串生成器 并初始化为指定的字符串内容 - 常用方法:
public StringBuilder append(数据类型)
:添加任意类型数据的字符串形式 并返回当前对象自身
public String toString()
:将当前StringBuilder对象转换为String对象
public class DemoStringBuiler {
public static void main(String[] args) {
//空参数构造方法
StringBuilder bu1 = new StringBuilder();
System.out.println("bu1:"+bu1);//bu1:
//带字符串的构造方法
StringBuilder bu2 = new StringBuilder("abs");
System.out.println("bu2:"+bu2);//bu2:abs
//创建StringBuilder对象
StringBuilder bu = new StringBuilder();
//使用append方法往StringBuilder中添加数据
StringBuilder bu3 = bu.append("abc");//把bu的地址赋值给了bu3
//append方法返回的是this 调用方法的对象bu 即this == bu
System.out.println("bu:"+bu);//bu:abc
System.out.println("bu3:"+bu3);//bu3:abc
System.out.println(bu==bu3);//比较的是地址 true
//使用append方法无需接收返回值
bu.append("abc");
bu.append(1);
bu.append(true);
bu.append(8.8);
bu.append('中');
System.out.println(bu);//abc1true8.8中
System.out.println("__________________________________");
//链式编程:方法返回值是一个对象 可以继续调用方法
bu.append("abc").append(1).append(true).append(8.8).append('中');
System.out.println(bu);//abcabc1true8.8中abc1true8.8中 为审美不是abc1true8.8中
}
}
四、StringBuilder和String可以相互转换:
- String转换为StringBuilder:可以使用StringBuilder的构造方法:
StringBuilder(String str)
:构造一个字符串生成器 并初始化为指定的字符串内容 - StringBuilder转换为String:可以使用StringBuilder中的toString方法:
public String toString()
:将当前StringBuilder对象转换为String对象
public class StringBuilderAndtoSting {
public static void main(String[] args) {
// String转换为StringBuilder:可以使用StringBuilder的构造方法:
String str = "hello";
System.out.println("str:"+str);
StringBuilder bu = new StringBuilder(str);
//往StringBuilder中添加数据
bu.append("world");
System.out.println("bu:"+bu);
// StringBuilder转换为String:可以使用StringBuilder中的toString方法
String s = bu.toString();
System.out.println("s:"+s);
}
}
java.lang.System
java.lang.System类中提供了大量的静态方法 可以获取与系统相关的信息或系统级操作 在System类的API文档中 常用方法有:
public static long currentTimeMillis()
:返回以毫秒为单位的当前时间public static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length)
:将数组中指定的数组拷贝到另一个数组
import java.util.Arrays;
public class DemoSystem {
public static void main(String[] args) {
demo01();
demo02();
System.out.println(System.currentTimeMillis());
}
/*piblic static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length):将数组中指定的数组拷贝到另一个数组
* 参数:
* src:源数组
* srcPos:源数组中的起始位置(起始索引)
* dest:目标数组
* destPos:目标数据中的起始位置
* Length:要复制的数组元素的数量
* 练习:将src数组中前三个元素复制到dest数组的前三个位置上
* 复制元素前:src数组元素{1,2,3,4,5},dest数组元素{6,7,8,9,10}
* 复制元素后 :src数组元素{1,2,3,4,5},dest数组元素{1,2,3,9,10}
*/
private static void demo02() {
int[] src = {1,2,3,4,5};//定义源数组
int[] dest = {6,7,8,9,10};//定义目标数组
System.out.println("复制前:"+Arrays.toString(dest));
//使用System类中的arraycopy把源数组的前三个元素复制到目标数组的前三个位置上
System.arraycopy(src,0,dest,0,3);
System.out.println("复制后:"+Arrays.toString(dest));
}
/*public static long currentTimeMillis():返回以毫秒为单位的当前时间
* 用来测试程序的效率
* 练习:验证for循环打印数字1-9999所需要使用的时间(毫秒)
*/
private static void demo01() {
long s = System.currentTimeMillis();//程序执行前获取一次毫秒值
for(int i = 1;i<=9999;i++) {//执行for循环
System.out.println(i);
}
long e = System.currentTimeMillis();//程序执行后获取一次毫秒值
System.out.println("程序共耗时:"+(e-s)+"毫秒");
}
}
java.lang.Object
一、object类是类层次结构的根类(父类) 所有对象(数组)都实现这个类的方法
二、toString()
:返回该对象的字符串表示
三、看一个类是否重写了toString 直接打印这个类的对象即可 如果没有重写那么打印的就是对象的地址值
public class ToString {
public static void main(String[] args) {
Person p = new Person("张三",18);
String s = p.toString();
System.out.println(s);//未重写toString的时候打印了s的地址值:Person@15db9742
//直接打印对象的名字其实就是调用对象的toString方法(如下)将会返回该对象的地址
//而我们需要该地址下的内容 所以需要重写toString方法(Person)
//重写toString之后打印的内容为Person(name=张三,age=18)
System.out.println(p);//未重写toString的时候打印了p的地址值:Person@15db9742
//重写toString之后打印的内容为Person(name=张三,age=18)
}
}
Person类默认继承了Object类 所以可以使用Object类中的ToString方法、equals方法
public class Person {
private String name;
private int age;
/*重写ToString*/
@Override
public String toString() {
return "Person(name="+name+",age="+age+")";//成员变量的name age
}
/*重写equals
* 由于隐含着多态 而多态的弊端是:无法使用子类特有的内容(属性和方法)
* Object obj = p2 = new Person("古力娜扎",19) 这就是一个多态 而父类object中不含有姓名和年龄
* 解决方法:可以使用向下转型(强制转型)把obj类型转换为Person
@Override
public boolean equals(Object obj) {
Person p = (Person)obj;//向下转型 把obj类型转换为Person
//比较两个对象的属性 一个对象是this(p1) 一个对象是p(obj p2)
boolean b = this.name.equals(p.name) && this.age==p.age;
return b;
}
*/
/*如果传递进来的是数组就没法比较 所以这样完善equals重写 防止类型转换失败*/
@Override
public boolean equals(Object obj) {
if(obj == this) {//如果是自己和自己比较 那么直接返回ture 不需要再转型再比较 提高程序效率
return true;
}
if(obj == null) {//如果传递进来的是null 那么直接返回false 不需要再转型再比较 提高程序效率
return false;
}
if(obj instanceof Person) {
Person p = (Person)obj;//向下转型 把obj类型转换为Person
//比较两个对象的属性 一个对象是this(p1) 一个对象是p(obj p2)
boolean b = this.name.equals(p.name) && this.age==p.age;
return b;
}
return false;//不是Person类型直接返回false
}
public Person() {
}
public Person(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;
}
}
java.util.Collection
一、java.util.Collection
接口:所有单列集合的最顶层接口 里面定义了所有单列集合共性的方法 任意的单列集合都可以使用Collection接口中的方法
二、共性的方法:
public boolean add(E e)
:把给定的对象添加到当前集合中public void clear()
:清空集合中所有的元素public boolean remove(E e)
:把给定的对象在当前集合中删除public boolean contains(E e)
:判断当前集合中是否包含给定的对象public boolean isEmpty()
:判断当前集合是否为空public int size()
:返回集合中元素的个数public Object[] toArray()
:把集合中的元素存储到数组中
import java.util.ArrayList;
import java.util.Collection;
public class CollectionClass {
public static void main(String[] args) {
//创建集合对象 可以使用多态
Collection<String> coll = new ArrayList<>();
System.out.println(coll);//[] 重写了toString方法
System.out.println("使用add方法:============================================");
/*
*public boolean add(E e):把给定的对象添加到当前集合中
*返回值是布尔值 一般都返回true 所以可以不用接收
*/
boolean b1 = coll.add("张三");
System.out.println("b1:" + b1);//b1:true
System.out.println(coll);//[张三]
coll.add("李四");
coll.add("王五");
coll.add("赵六");
coll.add("田七");
System.out.println(coll);//[张三, 李四, 王五, 赵六, 田七]
System.out.println("使用remove方法:==============================================");
/*
* public boolean remove(E e):把给定的对象在当前集合中删除
* 返回值是布尔值 集合中存在元素 删除元素 返回true 集合中不存在元素 删除失败 返回false
*/
boolean b2 = coll.remove("赵六");
System.out.println("b2:" + b2);
boolean b3 = coll.remove("赵四");
System.out.println("b3:" + b3);
System.out.println(coll);//[张三, 李四, 王五, 田七]
System.out.println("使用contains方法:==============================================");
/*
* public boolean contains(E e):判断当前集合中是否包含给定的对象
* 包含返回true 不包含返回false
*/
boolean b4 = coll.contains("李四");
System.out.println("b4:" + b4);
boolean b5 = coll.contains("赵四");
System.out.println("b5:" + b5);
System.out.println("使用isEmpty方法:==============================================");
//public boolean isEmpty():判断当前集合是否为空 集合为空返回true 集合不为空返回false
boolean b6 = coll.isEmpty();
System.out.println("b6:" + b6);
System.out.println("使用size方法:==============================================");
//public int size():返回集合中元素的个数
int size = coll.size();
System.out.println("size:" + size);
System.out.println("使用toArray方法:==============================================");
//public Object[] toArray():把集合中的元素存储到数组中
Object[] arr = coll.toArray();
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
System.out.println("使用clear方法:==============================================");
//public void clear():清空集合中所有的元素 但是不删除集合 集合还存在 只是里面的元素被删除了
coll.clear();
System.out.println(coll);//[]
}
}
java.util.Iterator
一、java.util.Iterator
接口:迭代器 对集合进行遍历 是一个接口 我们无法直接使用 需要使用Iterator接口的实现类对象,获取实现类的方式比较特殊 Collection接口中有一个方法叫Iterator()
这个方法返回的就是迭代器的实现类对象:Iterator<E> iterator()
:返回在此collection的元素上进行迭代的迭代器
二、迭代:即collection集合元素的通用获取方式 在取元素之前要先判断集合中有没有元素 如果有 就把这个元素取出来 继续再判断,如果还有就再取出来 一直把集合中的所有元素全部取出
三、常用方法:
boolean hasNext()
:如果仍有元素可以迭代 则返回true 判断集合中还有没有下一个元素 有就返回true 没有就返回falseE next()
:返回迭代的下一个元素 取出集合中的下一个元素
四、迭代器的使用步骤:
- 使用集合中的方法iterator()获取迭代器的实现类对象 使用Iterator接口接收(多态)
- 使用Iterator接口中的方法hasNext判断还有没有下一个元素
- 使用Iterator接口中的方法next取出集合中的下一个元素
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class IteratorInterface {
public static void main(String[] args) {
//创建一个集合对象
Collection<String> collection = new ArrayList<String>();
//往集合中添加元素
collection.add("姚明");
collection.add("科比");
collection.add("麦迪");
collection.add("詹姆斯");
collection.add("艾弗森");
/*
* (1)使用集合中的方法iterator()获取迭代器的实现类对象 使用Iterator接口接收(多态)
* 注意:Iterator<E>接口也是有泛型的 迭代器的泛型跟着集合走 集合是什么泛型 迭代器就是什么泛型
*/
Iterator<String> it = collection.iterator();//多态 左边接口 右边实现类对象
// (2)使用Iterator接口中的方法hasNext判断还有没有下一个元素
boolean b = it.hasNext();
System.out.println("b:" + b);
//(3)使用Iterator接口中的方法next取出集合中的下一个元素
//String string = it.next();
//System.out.println(string);//姚明
/*
* 发现使用迭代器取出集合中的元素一次只能取一个 要想取完 需要重复代码 所以我们可以使用循环优化
* 不知道集合中有多少元素 使用while循环 循环结束的条件是 hasNext方法返回false
*/
while (it.hasNext()) {
String e = (String) it.next();
System.out.println(e);
}
System.out.println("使用for循环:=============================================");
for(Iterator<String> it2 = collection.iterator();it2.hasNext();) {
String e = (String) it2.next();
System.out.println(e);
}
}
}
增强for循环
一、增强for循环:底层使用的也是迭代器 使用for循环的格式 简化了迭代器的书写 专门用来遍历数组和集合
二、Collection<E>extends Iterable<E>
:所有的单列集合都可以使用增强for循环 Collection继承了增强for
三、public interface Iterable<T>
:实现这个接口允许对象成为“foreach”语句的目标
四、格式:
for(集合/数组的数据类型 变量名:集合名/数组名){
System.out.println(变量名);
}
五、注意:增强型for循环必须有被遍历的目标 目标只能是Collection或者是数组 增强型for循环仅仅作为遍历操作出现
import java.util.ArrayList;
public class Foreach {
public static void main(String[] args) {
demo01();
demo02();
}
//遍历集合
private static void demo02() {
// TODO Auto-generated method stub
ArrayList<String> list = new ArrayList<String>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
for (String string : list) {
System.out.println(string);
}
}
//遍历数组
private static void demo01() {
// TODO Auto-generated method stub
int[] arr = {1,2,3,4,5};
for (int i : arr) {
System.out.println(i);
}
}
}
泛型
一、泛型:是一种未知的数据类型 但我们不知道使用什么数据类型的时候 可以使用泛型 也可以看成一个变量 用来接收数据类型
- E e:Element元素
- T t:Type类型
二、像下面的代码:ArrayList集合在定义时 不知道集合中都会存储什么类型的数据 所以类型使用泛型,其中E:未知的数据类型
public class ArrayList<E>{
public boolean add(E e){}
public E get(int index){}
}
三、创建集合时,就会确定泛型的数据类型:ArrayList<String> list = new ArrayList<String>();
,然后会把数据类型作为参数传递 把String赋值给泛型E 所有的E换成String
import java.awt.List;
import java.util.ArrayList;
import java.util.Iterator;
public class Generics {
public static void main(String[] args) {
//show01();
show2();
}
/*
* 创建集合 使用泛型
* 好处:
* 1.避免了类型转换的麻烦 存储的是什么类型 取出的就是什么类型
* 2.把运行期异常(代码运行后会抛出的异常),提升到了编译期(写代码时会报错)
* 坏处:泛型是什么类型 只能存储什么类型的数据
*/
private static void show2() {
ArrayList<String> list = new ArrayList<String>();
list.add("abc");
//list.add(1);错误 add(java.lang.Sring)in ArrayList cannot be applied to (int)
//使用迭代器遍历list集合
Iterator<String> iterator = list.iterator();
while(iterator.hasNext()) {
String string = iterator.next();
System.out.println(string + "->" + string.length());
}
}
/*
* 创建集合对象 不适用泛型
* 好处:集合不适用泛型 默认的类型就是Object类型 可以存储任意类型的数据
* 坏处:不安全 会引发异常
*/
private static void show01() {
ArrayList list = new ArrayList();//不适用泛型
list.add("abc");
list.add(1);
//迭代器遍历list集合
//获取迭代器
Iterator iterator = list.iterator();
//使用迭代器中的方法hasNext和next遍历集合
while(iterator.hasNext()) {
//取出元素也是object类型
Object object = iterator.next();
System.out.println(object);
//想要使用String类特有的方法 length获取字符串的长度 但现在使用的是多态 即Object object = "abc";
//需要向下转型 会抛出ClassCastException类型转换异常 不能把Integer类型转换为String类型
String string = (String)object;
System.out.println(string.length());
}
}
}
泛型方法
一、定义含有泛型的方法:泛型定义在方法的修饰符和返回值类型之间
格式:
修饰符 <泛型> 返回值类型 方法名(参数列表(使用泛型)){
方法体;
}
二、含有泛型的方法 在调用方法的时候确定泛型的数据类型,传递什么类型的参数 泛型就是什么类型
public class GenericMethod {
//定义一个含有泛型的方法
public <M> void method01(M m) {System.out.println(m);}
//定义一个含有泛型的静态方法
public static <S> void method02(S s) {System.out.println(s);}
}
三、测试含有泛型的方法
public class GenericMethod2 {
public static void main(String[] args) {
//创建GenericMethod对象
GenericMethod gm = new GenericMethod();
//调用含有泛型的方法method01 传递的是什么类型的参数 泛型就是什么类型
gm.method01(10);
gm.method01("abc");
gm.method01(8.8);
gm.method01(true);
//静态方法通过类名.方法名(参数)可以直接使用
GenericMethod.method02("静态方法");
GenericMethod.method02(1);
}
}
泛型的通配符
一、泛型的通配符:不知道使用什么类型来接收的时候 可以使用通配符?
,?
表示任意的数据类型 此时只能接受数据 不能往该集合中存储数据
二、使用方式:不能创建对象使用 只能作为方法的参数使用
import java.util.ArrayList;
import java.util.Iterator;
public class Generics2 {
public static void main(String[] args) {
ArrayList<Integer> list01 = new ArrayList<Integer>();
list01.add(1);
list01.add(2);
ArrayList<String> list02 = new ArrayList<String>();
list02.add("a");
list02.add("b");
//ArrayList<?> list03 = new ArrayList<?>();错误!在定义的时候不能使用通配符 只有在传递参数的时候才能用
printArray(list01);
printArray(list02);
}
/*
* 定义一个方法 能遍历所有类型的ArrayList集合
* 这时候我们不知道ArrayList集合使用什么数据类型 可以用泛型的通配符?来接受数据类型
* 【注】:泛型没有继承概念 所以不能写ArrayList<Object>
*/
private static void printArray(ArrayList<?> list01) {
//如果写ArrayList<Integer> 那么在主函数中调用printArray(list02);就会报错
//如果写ArrayList<String> 那么在主函数中调用printArray(list01);就会报错
//所以只能写ArrayList<?> 表示你给我任何数据类型我都能接收
//使用迭代器遍历集合
Iterator<?> iterator = list01.iterator();
while(iterator.hasNext()) {
//iterator.next()方法 取出的元素是object 因为只有object才能接收任意的数据类型
Object object = iterator.next();
System.out.println(object);
}
}
}
泛型的上、下限限定
一、泛型的上限限定:? extends E
代表使用的泛型只能是E类型的子类/本身
二、泛型的下限限定:? super E
代表使用的泛型只能是E类型的父类/本身
import java.util.ArrayList;
import java.util.Collection;
public class Generics3 {
public static void main(String[] args) {
Collection<Integer> list1 = new ArrayList<Integer>();
Collection<String> list2 = new ArrayList<String>();
Collection<Number> list3 = new ArrayList<Number>();
Collection<Object> list4 = new ArrayList<Object>();
getElement1(list1);
//getElement1(list2);错误 String与Number无关
getElement1(list3);
//getElement1(list4);错误 Object是Number的父类
//getElement2(list1);错误 Integer是Number的子类
//getElement2(list2);错误 String与Number无关
getElement2(list3);
getElement2(list4);
/*
* 类与类之间的继承关系:
* Integer extemds Number extends Object
* String extends Object
*/
}
//泛型的下限:此时的泛型?必须是Number类型或者Number类型的父类
public static void getElement2(Collection<? super Number> collection) {}
//泛型的上限:此时的泛型?必须是Number类型或者Number类型的子类
public static void getElement1(Collection<? extends Number> collection) {}
}
泛型的类的使用
一、定义一个含有泛型的类 模拟ArrayList集合
二、泛型是一个未知的数据类型 当我们不确定什么数据类型的时候 可以使用泛型
三、泛型可以接受任意的数据类型 可以使用Integer String Student等等
四、创建对象的时候确定泛型的数据类型
public class GenericClass<E> {
private E nameString;
public E getNameString() {return nameString;}
public void setNameString(E nameString) {this.nameString = nameString;}
}
public class GenericClass2 {
public static void main(String[] args) {
//不写泛型默认为Object类型
GenericClass gClass = new GenericClass();
gClass.setNameString("只能是字符串");//因为name是字符串类型
Object object = gClass.getNameString();
//创建GenericClass对象 泛型使用Integer类型
GenericClass<Integer> gClass2 = new GenericClass<Integer>();
gClass2.setNameString(1);
Integer nameInteger = gClass2.getNameString();
System.out.println(nameInteger);
//创建GenericClass对象 泛型使用String类型
GenericClass<String> gClass3 = new GenericClass<String>();
gClass3.setNameString("小明");
String nameString = gClass3.getNameString();
System.out.println(nameString);
}
}
泛型的接口的使用
一、定义含有泛型的接口:public interface GenericInterface<I> {public abstract void method(I i);}
二、测试含有泛型的接口
public class GenericInterface2 {
public static void main(String[] args) {
//创建GenericInterfaceImpl01对象
GenericInterfaceImpl01 gImpl01 = new GenericInterfaceImpl01();
gImpl01.method("字符串");
//创建GenericInterfaceImpl02对象
GenericInterfaceImpl02<Integer> gImpl02 = new GenericInterfaceImpl02<Integer>();
gImpl02.method(10);
GenericInterfaceImpl02<Double> gImpl03 = new GenericInterfaceImpl02<Double>();
gImpl03.method(8.8);
}
}
三、含有泛型的接口 第一种使用方式:定义接口的实现类实现接口 指定接口的泛型
public interface Iterator<E>{//Iterator接口含有泛型
E.next();//Iterator接口中的方法next()使用了泛型
}
// Scanner类实现了Iterator接口,并指定接口的泛型为String 所以重写的next方法泛型默认就是String
public final class Scanner implements Iterator<String>{
public String next(){}
}
public class GenericInterfaceImpl01 implements GenericInterface<String>{
@Override
public void method(String string) {System.out.println(string);}
}
四、含有泛型的接口第二种使用方式:接口使用什么泛型 实现类就使用什么泛型 类跟着接口走,就相当于定义了一个含有泛型的类 创建对象的时候确定泛型的类型
// ArrayList集合是List集合的实现类 List接口继承了Collection集合 List用了泛型
public interface List<E>{//List集合使用了泛型
boolean add(E e);//List集合中的方法add使用了泛型
E get(int index);//List集合中的方法get使用了泛型
}
public class ArrayList<E> implements List<E>{
public boolean add(E e){}
public E get(int index){}
}
public class GenericInterfaceImpl02<I> implements GenericInterface<I>{
@Override
public void method(I i) {
System.out.println(i);
}
}
java.utils.collections
一、java.utils.collections是集合工具类 用来对集合进行操作 部分方法如下:
public static <T> boolean addAll(Collection<T> c,T...elements)
:往集合中添加一些元素public static void shuffle(List<?> list)
:打乱集合顺序public static <T> void sort(List<T> list)
:将集合中的元素按照默认规则排序 默认升序public static <T> void sort(List<T> list,Comparator<? super T>)
:将集合中元素按照指定规则排序List<T> list
指集合Comparator<? super T>
指排序规则
【注】:Comparable与Comparator的区别:
- Comparable:自己(this)和别人(传递进来的参数o)比较,自己需要实现
Comparable
接口,重写比较的规则compareTo
方法- Comparator:相当于找一个第三方的裁判,比较两个
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class CollectionsClass {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "a","b","c","d","e");
System.out.println(list);//[a, b, c, d, e]
Collections.shuffle(list);
System.out.println(list);//[e, c, b, a, d]
Collections.sort(list);
System.out.println(list);//[a, b, c, d, e]
ArrayList<PersonCollections> list2 = new ArrayList<PersonCollections>();
list2.add(new PersonCollections("张三",18));
list2.add(new PersonCollections("b李四",20));
list2.add(new PersonCollections("王五",15));
list2.add(new PersonCollections("a张三",20));
System.out.println(list2);//[PersonCollections [PersonCollections [nameString=张三, age=18], PersonCollections [nameString=李四, age=20], PersonCollections [nameString=王五, age=15], PersonCollections [nameString=张三, age=20]]
Collections.sort(list2);//如果不在PersonCollections中重写排序的规则 此处会报错
//注意:sort方法使用前提:被排序的集合里边存储的元素必须实现Comparable 重写接口中的方法compareTo定义排序的规则
System.out.println(list2);//[PersonCollections [PersonCollections [nameString=王五, age=15], PersonCollections [nameString=张三, age=18], PersonCollections [nameString=李四, age=20], PersonCollections [nameString=张三, age=20]]
ArrayList<Integer> list3 = new ArrayList<Integer>();
list3.add(1);
list3.add(3);
list3.add(2);
System.out.println(list3);//[1, 3, 2]
Collections.sort(list3,new Comparator<Integer>() {
//重写比较的规则
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;//升序 如果是:O2 - O1就是降序
}
});
System.out.println(list3);//[1, 2, 3]
Collections.sort(list2,new Comparator<PersonCollections>() {
@Override
public int compare(PersonCollections o1, PersonCollections o2) {
//return o1.getAge() - o2.getAge();//按照年龄升序排序 当出现两个年龄相同 名字不同的人时 系统按照添加顺序进行打印输出
/*
* 正常情况下 当出现两个年龄相同 名字不同的人时 系统按照添加顺序进行打印输出 但是如果我们希望此时根据名字的第一个字进行排序输出 此时应该这样:
* 为了方便比较观察 我们先将姓名前面添加不同的字母
*/
int result = o1.getAge() - o2.getAge();
if (result == 0) {
result = o1.getNameString().charAt(0) - o2.getNameString().charAt(0);
}
return result;
}
});
System.out.println(list2);//[PersonCollections [PersonCollections [nameString=王五, age=15], PersonCollections [nameString=张三, age=18], PersonCollections [nameString=李四, age=20], PersonCollections [nameString=张三, age=20]]
}
}
/*
* 添加hashCode equals方法是为了保证set集合元素唯一
*/
public class PersonCollections implements Comparable<PersonCollections/*对什么类型进行排序 这里就写什么类型*/>{
private String nameString;
private int age;
@Override
public String toString() {
return "PersonCollections [nameString=" + nameString + ", age=" + age + "]";
}
public String getNameString() {return nameString;}
public void setNameString(String nameString) {this.nameString = nameString;}
public int getAge() {return age;}
public void setAge(int age) {this.age = age;}
public PersonCollections(String nameString, int age) {
super();
this.nameString = nameString;
this.age = age;
}
public PersonCollections() {super();}
//重写排序的规则
@Override
public int compareTo(PersonCollections o) {
//return 0;认为元素都是相同的
//自定义比较的规则 比较两个人的年龄(this和传递过来的参数person这两个人)
return this.getAge() - o.getAge();//Comparable接口的排序规则:自己(this) - 参数 升序。参数 - 自己(this) 降序
}
}