文章目录

  • 前言
  • 一、常用API
    • 1.Object(祖宗类)
    • 2.Objects(工具类-提供一些方法完成一些功能)
    • 3.StringBuilder(不可变的字符串类)
    • 4.Math(基本数字运算的方法)
    • 5.System(工具类)
    • 6.BigDecimal(用于解决浮点型运算精度失真的问题)
    • 7.Date
    • 8.SimpleDateFormat
    • 9.Calendar
    • 10.包装类
  • 二、正则表达式、Arrays类、Lambda表达式
    • 1、正则表达式
    • 2.Arrays类
    • 3.Lambda表达式
  • 三、集合
    • 1.Collection(单列集合的祖宗接口)
    • 2.数据结构(红黑树)
    • 3.List(ArrayList,LinkedList)
    • 4.泛型(泛型类、泛型方法、泛型接口、通配符)
    • 5.Set(HashSet,LInkedHashSet,TreeSet)
    • 6.Collections(集合工具类)
    • 7.Map(键值对集合)
    • 8.集合嵌套
  • 四、不可变集合、Stream、异常
    • 1.不可变集合
    • 2.Stream
    • 3.异常
  • 总结

前言

主要是记录学习Java时的笔记,这篇学习的是的常用API、正则表达式、Lambda、算法和集合(Collection、数据结构、LIst、泛型深入、Set、Collection、Map、集合嵌套、不可变集合、Stream、异常


提示:以下是本篇文章正文内容

一、常用API

什么是API?:应用程序编程接口(就是Java帮我们写好的一些方法,我们直接拿过来用就可以了)


1.Object(祖宗类)

父类toString()方法存在的意义是为了被子类重写,以便返回对象的内容信息,而不是地址信息!!
父类equals()方法存在的意义就是为了被子类重写,以便子类自己来定制比较规制(如比较两个子类对象的内容是否相同)!!,如果比较两个对象的地址可以用“==”代替

代码实例如下

    @Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", sex=" + sex +", age=" + age +'}';}
}
public class Test2 {public static void main(String[] args) {Student s1 = new Student("周雄", '男', 19);Student s2 = new Student("周雄", '男', 19);// equals默认是比较2个对象的地址是否相同,子类重写后会调用子类重写的来比较内容是否相同。System.out.println(s1.equals(s2));System.out.println(s1 == s2);System.out.println(Objects.equals(s1, s2));}
}//        比较者:s1 == this
//        被比较者: s2 ==> o@Overridepublic boolean equals(Object o){// 1、判断o是不是学生类型if(o instanceof Student){Student s2 = (Student) o;// 2、判断2个对象的内容是否一样。
//            if(this.name.equals(s2.name) &&
//                 this.age == s2.age && this.sex == s2.sex){//                return true;
//            }else {//                return false;
//            }return this.name.equals(s2.name) && this.age == s2.age&& this.sex == s2.sex ;}else {// 学生只能和学生比较,否则结果一定是falsereturn false;}}
//        比较者:s1 == this
//        被比较者: s2 ==> o@Override//改进版--IDEA自动生成的代码public boolean equals(Object o) {// 1、判断是否是同一个对象比较,如果是返回true。if (this == o) return true;// 2、如果o是null返回false  如果o不是学生类型返回false  ...Student !=  ..Pigif (o == null || this.getClass() != o.getClass()) return false;// 3、说明o一定是学生类型而且不为nullStudent student = (Student) o;return sex == student.sex && age == student.age && Objects.equals(name, student.name);}

2.Objects(工具类-提供一些方法完成一些功能)

官方在进行字符串比较时,没有用字符串对象的equals方法,而是选择equals方法来比较(更安全-内部会进行非空校验)

实例代码

public class Test {public static void main(String[] args) {String s1 = null;String s2 = new String("itheima");// System.out.println(s1.equals(s2));   // 留下了隐患,可能出现空指针异常。System.out.println(Objects.equals(s1, s2)); // 更安全,结果也是对的!/**Objects:public static boolean equals(Object a, Object b) {return (a == b) || (a != null && a.equals(b));}*/System.out.println(Objects.isNull(s1)); // trueSystem.out.println(s1 == null); // trueSystem.out.println(Objects.isNull(s2)); // falseSystem.out.println(s2 == null); // false}
}

3.StringBuilder(不可变的字符串类)

可以把它看成是一个对象容器,提高字符串的操作效率,如拼接、修改等

注意:StringBuilder只是拼接字符串的手段,效率好(支持追加,反转,链式编程),最终的目的还是要恢复成String类型

实例代码

public class StringBuilderDemo1 {public static void main(String[] args) {StringBuilder sb = new StringBuilder(); // ""sb.append("a");sb.append(1);sb.append(false);sb.append(3.3);sb.append("abc");System.out.println(sb);StringBuilder sb1 = new StringBuilder();// 支持链式编程sb1.append("a").append("b").append("c").append("我爱你中国");System.out.println(sb1);// 反转sb1.reverse().append("110");System.out.println(sb1);System.out.println(sb1.length());// 注意:StringBuilder只是拼接字符串的手段:效率好。// 最终的目的还是要恢复成String类型。StringBuilder sb2 = new StringBuilder();sb2.append("123").append("456");// 恢复成String类型String rs = sb2.toString();check(rs);}public static void check(String data){System.out.println(data);}
}

定义字符串使用String,拼接、修改等操作字符串使用StringBuilder

String类拼接字符串原理图-String内容时不可变的,拼接字符串性能差

StringBuilder提高效率原理图-内容时可变的,拼接字符串性能好,代码优雅

案例-打印数组内容


public class StringBuilderTest2 {public static void main(String[] args) {int[] arr1 = null;System.out.println(toString(arr1));int[] arr2 = {10, 88, 99};System.out.println(toString(arr2));int[] arr3 = {};System.out.println(toString(arr3));}/**1、定义方法接收任意整型数组,返回数组内容格式*/public static String toString(int[] arr){if(arr != null){// 2、开始拼接内容。StringBuilder sb = new StringBuilder("[");for (int i = 0; i < arr.length; i++) {sb.append(arr[i] ).append(i == arr.length - 1 ? "" : ", ");}sb.append("]");return sb.toString();//最后转换回字符串}else {return null;}}
}//输出结果
//null
//[10,88,99]
//[]

4.Math(基本数字运算的方法)

Math类(工具类)没有提供公开的构造器,如果类中的成员是静态的话,可以用类名直接调用

实例代码

 System.out.println(Math.random());  // 0.0 - 1.0 (包前不包后)// 拓展: 3 - 9 之间的随机数  (0 - 6) + 3//  [0 - 6] + 3int data =  (int)(Math.random() * 7) + 3;System.out.println(data);

5.System(工具类)

代表了当前系统,提供了一些与系统相关的方法

实例代码

public class SystemDemo {public static void main(String[] args) {System.out.println("程序开始。。。");// System.exit(0); // JVM终止!// 2、计算机认为时间有起源:返回1970-1-1 00:00:00 走到此刻的总的毫秒值:时间毫秒值。long time = System.currentTimeMillis();System.out.println(time);long startTime = System.currentTimeMillis();// 进行时间的计算:性能分析for (int i = 0; i < 100000; i++) {System.out.println("输出:" + i);}long endTime = System.currentTimeMillis();System.out.println((endTime - startTime)/1000.0 + "s");// 3、做数组拷贝(了解)/**arraycopy(Object src,  int  srcPos,Object dest, int destPos,int length)参数一:被拷贝的数组参数二:从哪个索引位置开始拷贝参数三:复制的目标数组参数四:粘贴位置参数五:拷贝元素的个数*/int[] arr1 = {10, 20, 30, 40, 50, 60, 70};int[] arr2 = new int[6]; // [0, 0, 0, 0, 0, 0] ==>  [0, 0, 40, 50, 60, 0]System.arraycopy(arr1, 3, arr2, 2, 3);System.out.println(Arrays.toString(arr2));System.out.println("-------------------");double i = 10.0;double j = 3.0;
//        System.out.println(k1);System.out.println("程序结束。。。。");}
}

6.BigDecimal(用于解决浮点型运算精度失真的问题)

实例代码

public class BigDecimalDemo {public static void main(String[] args) {// 浮点型运算的时候直接+  * / 可能会出现数据失真(精度问题)。System.out.println(0.09 + 0.01);System.out.println(1.0 - 0.32);System.out.println(1.015 * 100);System.out.println(1.301 / 100);System.out.println("-------------------------");double a = 0.1;double b = 0.2;double c = a + b;System.out.println(c);System.out.println("--------------------------");// 包装浮点型数据成为大数据对象 BigDeciamlBigDecimal a1 = BigDecimal.valueOf(a);BigDecimal b1 = BigDecimal.valueOf(b);BigDecimal c1 = a1.add(b1);// BigDecimal c1 = a1.subtract(b1);// BigDecimal c1 = a1.multiply(b1);// BigDecimal c1 = a1.divide(b1);System.out.println(c1);// 目的:doubledouble rs = c1.doubleValue();System.out.println(rs);// 注意事项:BigDecimal是一定要精度运算的BigDecimal a11 = BigDecimal.valueOf(10.0);//获取BigDecimal对象BigDecimal b11 = BigDecimal.valueOf(3.0);/**参数一:除数 参数二:保留小数位数  参数三:四舍五入模式(其它还有进一法、去尾法)*/BigDecimal c11 = a11.divide(b11, 2, RoundingMode.HALF_UP); // 3.3333333333System.out.println(c11);System.out.println("-------------------");}
}

7.Date

Date类代表当前所在系统的日期时间信息

案例–请计算出当前时间往后走1小时121秒之后的时间是多少(获取时间毫秒值,然后恢复成日期对象)

    public static void main(String[] args) {// 1、得到当前时间Date d1 = new Date();System.out.println(d1);// 2、当前时间往后走 1小时  121slong time2 = System.currentTimeMillis();time2 += (60 * 60 + 121) * 1000;// 3、把时间毫秒值转换成对应的日期对象。// Date d2 = new Date(time2);// System.out.println(d2);Date d3 = new Date();d3.setTime(time2);System.out.println(d3);}

8.SimpleDateFormat

可以完成日期时间的格式化操作

实例代码—格式化标准的时间形式

 public static void main(String[] args) {// 1、日期对象Date d = new Date();System.out.println(d);// 2、格式化这个日期对象 (指定最终格式化的形式)SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss EEE a");// 3、开始格式化日期对象成为喜欢的字符串形式String rs = sdf.format(d);System.out.println(rs);System.out.println("----------------------------");// 4、格式化时间毫秒值// 需求:请问121秒后的时间是多少long time1 = System.currentTimeMillis() + 121 * 1000;String rs2 = sdf.format(time1);System.out.println(rs2);}

案例

示例代码----解析时间

public class SimpleDateFormatDemo2 {public static void main(String[] args) throws ParseException {// 目标: 学会使用SimpleDateFormat解析字符串时间成为日期对象。// 有一个时间 2021年08月06日 11:11:11 往后 2天 14小时 49分 06秒后的时间是多少。// 1、把字符串时间拿到程序中来String dateStr = "2021年08月06日 11:11:11";// 2、把字符串时间解析成日期对象(本节的重点):形式必须与被解析时间的形式完全一样,否则运行时解析报错!SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");Date d = sdf.parse(dateStr);// 3、往后走2天 14小时 49分 06秒long time = d.getTime() + (2L*24*60*60 + 14*60*60 + 49*60 + 6) * 1000;//要加L防止数据越界// 4、格式化这个时间毫秒值就是结果System.out.println(sdf.format(time));}
}

案例—秒杀活动

实例代码

 public static void main(String[] args) throws ParseException {// 1、开始 和 结束时间String startTime = "2021-11-11 00:00:00";String endTime = "2021-11-11 00:10:00";// 2、小贾 小皮String xiaoJia =  "2021-11-11 00:03:47";String xiaoPi =  "2021-11-11 00:10:11";// 3、解析他们的时间SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");Date d1 = sdf.parse(startTime);Date d2 = sdf.parse(endTime);Date d3 = sdf.parse(xiaoJia);Date d4 = sdf.parse(xiaoPi);if(d3.after(d1) && d3.before(d2)){System.out.println("小贾秒杀成功,可以发货了!");}else {System.out.println("小贾秒杀失败!");}if(d4.after(d1) && d4.before(d2)){System.out.println("小皮秒杀成功,可以发货了!");}else {System.out.println("小皮秒杀失败!");}}

9.Calendar

Calendar代表了系统此刻日期对应的日历对象,它是一个抽象类不能创建对象


calendar是可变日期对象,一旦修改后其对象本身表示的时间将产生变化

实例代码

  public static void main(String[] args) {// 1、拿到系统此刻日历对象Calendar cal = Calendar.getInstance();System.out.println(cal);// 2、获取日历的信息:public int get(int field):取日期中的某个字段信息。int year = cal.get(Calendar.YEAR);System.out.println(year);int mm = cal.get(Calendar.MONTH) + 1;System.out.println(mm);int days = cal.get(Calendar.DAY_OF_YEAR) ;System.out.println(days);// 3、public void set(int field,int value):修改日历的某个字段信息。// cal.set(Calendar.HOUR , 12);// System.out.println(cal);// 4.public void add(int field,int amount):为某个字段增加/减少指定的值// 请问64天后是什么时间cal.add(Calendar.DAY_OF_YEAR , 64);cal.add(Calendar.MINUTE , 59);//  5.public final Date getTime(): 拿到此刻日期对象。Date d = cal.getTime();System.out.println(d);//  6.public long getTimeInMillis(): 拿到此刻时间毫秒值long time = cal.getTimeInMillis();System.out.println(time);


10.包装类

就是8种基本数据类型对应的引用类型

Java为了实现一切皆对象,为8种基本类型提供了对应的引用类型]
集合和泛型只能支持包装类型,而不支持基本数据类型

自动装箱:基本类型的数据和变量可以直接赋值给包装类型的变量。

自动拆箱:包装类型的变量可以直接赋值给基本数据类型的变量

包装类特有的功能:
1、包装类的变量默认值可以是null,容错率更高。
2、可以把基本数据类型转换成字符串类型。
3、可以把字符串类型的数值转换成真实的数据类型

String number = "23";//转换成整数// int age = Integer.parseInt(number);int age = Integer.valueOf(number);System.out.println(age + 1);String number1 = "99.9";//转换成小数
//        double score = Double.parseDouble(number1);double score = Double.valueOf(number1);System.out.println(score + 0.1);

二、正则表达式、Arrays类、Lambda表达式


1、正则表达式

正则表达式可以用一些规定的字符来制定规制,并用来检验数据格式的合法性

案例

示例代码

public static void main(String[] args) {// 需求:校验qq号码,必须全部数字 6 - 20位System.out.println(checkQQ("251425998"));//trueSystem.out.println(checkQQ("2514259a98"));//falseSystem.out.println(checkQQ(null));//falseSystem.out.println(checkQQ("2344"));//falseSystem.out.println("-------------------------");// 正则表达式的初体验:System.out.println(checkQQ2("251425998"));System.out.println(checkQQ2("2514259a98"));System.out.println(checkQQ2(null));System.out.println(checkQQ2("2344"));}//正则表达式判断public static boolean checkQQ2(String qq){//\d代表都是数字,\转译字符,return qq != null && qq.matches("\\d{6,20}");}public static boolean checkQQ(String qq){// 1、判断qq号码的长度是否满足要求if(qq == null || qq.length() < 6 || qq.length() > 20 ) {return false;}// 2、判断qq中是否全部是数字,不是返回false//  251425a87for (int i = 0; i < qq.length(); i++) {// 获取每位字符char ch = qq.charAt(i);// 判断这个字符是否不是数字,不是数字直接返回falseif(ch < '0' || ch > '9') {return false;}}return true; // 肯定合法了!}

正则表达式的匹配规则字符串对象提供了匹配正则表达式规则的API

示例代码

 // 校验密码// 必须是数字 字母 下划线 至少 6位System.out.println("2442fsfsf".matches("\\w{6,}"));//trueSystem.out.println("244f".matches("\\w{6,}"));//false// 验证码 必须是数字和字符  必须是4位System.out.println("23dF".matches("[a-zA-Z0-9]{4}"));//trueSystem.out.println("23_F".matches("[a-zA-Z0-9]{4}"));//falseSystem.out.println("23dF".matches("[\\w&&[^_]]{4}"));//trueSystem.out.println("23_F".matches("[\\w&&[^_]]{4}"));//false

案例

示例代码

  public static void main(String[] args) {// 目标:校验 手机号码 邮箱  电话号码// checkPhone();// checkEmail();// checkTel();// 同学可以完成校验金额是否格式金额: 99  0.5  99.5  019   | 0.3.3int[] arr = {10, 4, 5,3, 4,6,  2};System.out.println(Arrays.binarySearch(arr, 2));}public static void checkTel(){Scanner sc = new Scanner(System.in);while (true) {System.out.println("请您输入您的电话号码:");String tel = sc.next();// 判断邮箱格式是否正确   027-3572457  0273572457if(tel.matches("0\\d{2,6}-?\\d{5,20}")){System.out.println("格式正确,注册完成!");break;}else {System.out.println("格式有误!");}}}public static void checkEmail(){Scanner sc = new Scanner(System.in);while (true) {System.out.println("请您输入您的注册邮箱:");String email = sc.next();// 判断邮箱格式是否正确   3268847878@qq.com// 判断邮箱格式是否正确   3268847dsda878@163.com// 判断邮箱格式是否正确   3268847dsda878@pci.com.cnif(email.matches("\\w{1,30}@[a-zA-Z0-9]{2,20}(\\.[a-zA-Z0-9]{2,20}){1,2}")){System.out.println("邮箱格式正确,注册完成!");break;}else {System.out.println("格式有误!");}}}public static void checkPhone(){Scanner sc = new Scanner(System.in);while (true) {System.out.println("请您输入您的注册手机号码:");String phone = sc.next();// 判断手机号码的格式是否正确if(phone.matches("1[3-9]\\d{9}")){System.out.println("手机号码格式正确,注册完成!");break;}else {System.out.println("格式有误!");}}}

正则表达式在字符串方法中的使用

示例代码

public static void main(String[] args) {String names = "小路dhdfhdf342蓉儿43fdffdfbjdfaf小何";String[] arrs = names.split("\\w+");//从字符数字下划线开始分割for (int i = 0; i < arrs.length; i++) {System.out.println(arrs[i]);//小路-蓉儿-小何}String names2 = names.replaceAll("\\w+", "  ");//小路  蓉儿  小何System.out.println(names2);}

正则表达式支持爬取信息


public static void main(String[] args) {String rs = "跟黑马程序学习Java,电话020-43422424,或者联系邮箱" +"itcast@itcast.cn,电话18762832633,0203232323" +"邮箱bozai@itcast.cn,400-100-3233 ,4001003232";// 需求:从上面的内容中爬取出 电话号码和邮箱。// 1、定义爬取规则,字符串形式String regex = "(\\w{1,30}@[a-zA-Z0-9]{2,20}(\\.[a-zA-Z0-9]{2,20}){1,2})|(1[3-9]\\d{9})" +"|(0\\d{2,6}-?\\d{5,20})|(400-?\\d{3,9}-?\\d{3,9})";// 2、把这个爬取规则编译成匹配对象。Pattern pattern = Pattern.compile(regex);// 3、得到一个内容匹配器对象Matcher matcher = pattern.matcher(rs);// 4、开始找了while (matcher.find()) {String rs1 = matcher.group();//每找到一组取一组System.out.println(rs1);}}

2.Arrays类

数组操作工具类,专门用于操作数组元素的。

示例代码

@Override//需重写toString(),不然返回的是地址public String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", height=" + height +'}';}Student[] students = new Student[3];students[0] = new Student("吴磊",23 , 175.5);students[1] = new Student("谢鑫",18 , 185.5);students[2] = new Student("王亮",20 , 195.5);System.out.println(Arrays.toString(students));// Arrays.sort(students);  // 直接运行奔溃/**参数一:被排序的数组 必须是引用类型的元素参数二:匿名内部类对象,代表了一个比较器对象。*///Lambda简化形式
Arrays.sort(students,(Student  o1,Student  o2)->{return Double.compare(o2.getHeight(),   o1.getHeight()); });
/Arrays.sort(students, new Comparator<Student>() {@Overridepublic int compare(Student o1, Student o2) {// 自己指定比较规则// return o1.getAge() - o2.getAge(); // 按照年龄升序排序!// return o2.getAge() - o1.getAge(); // 按照年龄降序排序!!// return Double.compare(o1.getHeight(), o2.getHeight()); // 比较浮点型可以这样写 升序return Double.compare(o2.getHeight(), o1.getHeight()); // 比较浮点型可以这样写  降序}});System.out.println(Arrays.toString(students));

3.Lambda表达式

Lambda表达式是JDK8开始后的一种新语法形式
主要是简化匿名内部类的代码写法(只能简化函数式接口的匿名内部类的写法形式)

函数式接口:必须是接口,其次接口中有且仅有一个抽象方法的形式

示例代码–简化过程


public class LambdaDemo2 {public static void main(String[] args) {// 目标:学会使用Lambda的标准格式简化匿名内部类的代码形式// 注意:Lambda只能简化接口中只有一个抽象方法的匿名内部类形式(函数式接口)
//        Swimming s1 = new Swimming() {//            @Override
//            public void swim() {//                System.out.println("老师游泳贼溜~~~~~");
//            }
//        };//        Swimming s1 = () -> {//            System.out.println("老师游泳贼溜~~~~~");
//        };Swimming s1 = () -> System.out.println("老师游泳贼溜~~~~~");go(s1);System.out.println("---------------------");
//        go(new Swimming() {//            @Override
//            public void swim() {//                System.out.println("学生游泳很开心~~~");
//            }
//        });//        go(() ->{//                System.out.println("学生游泳很开心~~~");
//        });go(() -> System.out.println("学生游泳很开心~~~"));}public static void go(Swimming s){System.out.println("开始。。。");s.swim();System.out.println("结束。。。");}
}@FunctionalInterface // 一旦加上这个注解必须是函数式接口,里面只能有一个抽象方法interface Swimming{void swim();}

Lambda表达式的省略写法

1、参数类型可以省略不写,如果只有一个参数,同时()也可以省略不写
2、如果方法体代码只有一行代码,可以省略大括号不写,同时省略分号如果这行代码是return语句,必须省略return不写,同时也必须省略“;”不写。

示例代码

Arrays.sort(ages1, new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return o2 - o1; //  降序}});//Lambda简化Arrays.sort(ages1, (Integer o1, Integer o2) -> {return o2 - o1; //  降序});Arrays.sort(ages1, ( o1,  o2) -> {return o2 - o1; //  降序});//return不写,分号不写Arrays.sort(ages1, ( o1,  o2 ) ->  o2 - o1 );btn.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {System.out.println("有人点我,点我,点我!!");}});//Lambda简化btn.addActionListener((ActionEvent e) -> {System.out.println("有人点我,点我,点我!!");});//一个参数的话,参数类型可以不写btn.addActionListener(( e) -> {System.out.println("有人点我,点我,点我!!");});//一个参数的话,()可以不写btn.addActionListener( e -> {System.out.println("有人点我,点我,点我!!");});//大括号不写,分号不写btn.addActionListener( e -> System.out.println("有人点我,点我,点我!!") );

三、集合

集合的类型不固定,大小是可变的,并且只能储存引用类型的数据.集合适合做数据个数不确定,且要做增删元素的场景
集合都是支持泛型的,可以在编译阶段约束集合只能操作某种数据类型(JDK1.7开始后面的泛型类型声明可以省略不写)

集合和泛型都只能支持引用数据类型,不支持基本数据类型,所以集合中存储的元素都认为是对象


1.Collection(单列集合的祖宗接口)

每个元素只包含一个值,它的功能是全部单列集合都可以继承使用的

集合的遍历方式

1、迭代器(Iterator):默认指向当前集合的索引0,如果取元素越界会出现NoSuchElenmentException异常

2、foreach(增强for循环JDK5之后)既可以遍历集合也可以遍历数组

示例代码

public static void main(String[] args) {Collection<String> lists = new ArrayList<>();lists.add("赵敏");lists.add("小昭");lists.add("殷素素");lists.add("周芷若");System.out.println(lists);// [赵敏, 小昭, 殷素素, 周芷若]//  elefor (String ele : lists) {System.out.println(ele);}System.out.println("------------------");double[] scores = {100, 99.5 , 59.5};for (double score : scores) {System.out.println(score);
//            if(score == 59.5){//修改第三方变量的值不会影响到集合中的值
//                score = 100.0; // 修改无意义,不会影响数组的元素值。
//            }}System.out.println(Arrays.toString(scores));}

3、Lambda表达式(JDK 8开始):

示例代码

public static void main(String[] args) {Collection<String> lists = new ArrayList<>();lists.add("赵敏");lists.add("小昭");lists.add("殷素素");lists.add("周芷若");System.out.println(lists);// [赵敏, 小昭, 殷素素, 周芷若]//  slists.forEach(new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}});//Lambda表达式遍历的改进版lists.forEach(s -> { System.out.println(s); });lists.forEach(s ->  System.out.println(s) );//方法引用遍历方式lists.forEach(System.out::println );}

集合中存储的是元素对象的地址


2.数据结构(红黑树)

是计算机底层存储,组织数据的方式

红黑树是一种自平衡的二叉查找树,是计算机科学中用到的一种数据结构

它的节点可以是红或者黑根节点、叶节点Nil必须是黑色的,且不能出现两个红色节点相连的情况,红黑树不是通过高度平衡的,它的平衡是通过红黑规则进行的。对每一个节点,从该节点到其所有后代节点的简单路径上,均包含相同数目的黑色节点

红黑树添加节点默认用红色效率高



3.List(ArrayList,LinkedList)

添加的元素是有序的,可重复,有索引
ArrayList底层的数据结构是数组
LinkedList底层的数据结构是双链表,定位前后的元素是非常快的,可以实现栈和队列的功能

示例代码–集合遍历并删除元素可能出现的异常及改进方式

public static void main(String[] args) {// 1、准备数据ArrayList<String> list = new ArrayList<>();list.add("黑黑");list.add("Java");list.add("Java");list.add("赵敏");list.add("赵敏");list.add("素素");System.out.println(list);// [黑黑, Java, Java, 赵敏, 赵敏, 素素]//        it// 需求:删除全部的Java信息。// a、迭代器遍历删除Iterator<String> it = list.iterator();while (it.hasNext()){String ele = it.next();if("Java".equals(ele)){// 删除Java// list.remove(ele); // 集合删除会出毛病it.remove(); // 删除迭代器所在位置的元素值(没毛病)}}System.out.println(list);// b、foreach遍历删除 (会出现问题,这种无法解决的,foreach不能边遍历边删除,会出bug)for (String s : list) {if("Java".equals(s)){list.remove(s);}}// c、lambda表达式(会出现问题,这种无法解决的,Lambda遍历不能边遍历边删除,会出bug)list.forEach(s -> {//底层的逻辑是foreach()if("Java".equals(s)){list.remove(s);}});// d、for循环(边遍历边删除集合没毛病,但是必须从后面开始遍历删除才不会出现漏掉应该删除的元素)for (int i = list.size() - 1; i >= 0 ; i--) {String ele = list.get(i);if("Java".equals(ele)){list.remove(ele);}}System.out.println(list);}

4.泛型(泛型类、泛型方法、泛型接口、通配符)

在编译阶段约束操作的数据类型,并进行检查
泛型只能支持引用数据类型,集合体系的全部接口和实现类都是支持泛型的使用的

泛型的好处是统一数据类型,把运行时期的问题提前到编译期间,避免了强制类型转换可能出现的异常,因为编译阶段类型就能确定下来

泛型类定义类的同时定义了泛型的类就是泛型类

示例代码


public class MyArrayList<E> {private ArrayList lists = new ArrayList();
//套壳子,内部用的还是ArrayList//装饰模式的思想-外部对象包一个内部对象public void add(E e){lists.add(e);}public void remove(E e){//这个方法不是泛型方法,e是类上面定义的lists.remove(e);}@Overridepublic String toString() {return lists.toString();}
}public static void main(String[] args) {// 需求:模拟ArrayList定义一个MyArrayList ,关注泛型设计MyArrayList<String> list = new MyArrayList<>();list.add("Java");list.add("Java");list.add("MySQL");list.remove("MySQL");System.out.println(list);MyArrayList<Integer> list2 = new MyArrayList<>();list2.add(23);list2.add(24);list2.add(25);list2.remove(25);System.out.println(list2);}

泛型方法—定义方法时的同时定义了泛型的方法就是泛型方法`

示例代码


public class GenericDemo {public static void main(String[] args) {String[] names = {"小璐", "蓉容", "小何"};printArray(names);Integer[] ages = {10, 20, 30};printArray(ages);Integer[] ages2 = getArr(ages);String[]  names2 = getArr(names);}public static <T> T[] getArr(T[] arr){return arr;}public static <T> void printArray(T[] arr){if(arr != null){StringBuilder sb = new StringBuilder("[");for (int i = 0; i < arr.length; i++) {sb.append(arr[i]).append(i == arr.length - 1 ? "" : ", ");}sb.append("]");System.out.println(sb);}else {System.out.println(arr);}}
}

泛型接口 使用了泛型定义的接口就是泛型接口,可以让实现类选择当前功能需要操作的数据类型

示例代码 泛型接口可以约束实现类,实现类可以在实现接口的时候传入自己操作的数据类型,这样重写的方法都是针对该类型的操作

//定义了一个泛型接口
public interface Data<E> {void add(E e);void delete(int id);void update(E e);E queryById(int id);
}
public class Student {}
public class StudentData implements Data<Student>{@Overridepublic void add(Student student) {}@Overridepublic void delete(int id) {}@Overridepublic void update(Student student) {}@Overridepublic Student queryById(int id) {return null;}
}

通配符可以在使用泛型的时候代表一切类型,ETKV实在定义泛型的时候使用的

案例-开发一个极品飞车的游戏,所有汽车都能一起参加比赛。

示例代码

public class GenericDemo {public static void main(String[] args) {ArrayList<BMW> bmws = new ArrayList<>();bmws.add(new BMW());bmws.add(new BMW());bmws.add(new BMW());go(bmws);ArrayList<BENZ> benzs = new ArrayList<>();benzs.add(new BENZ());benzs.add(new BENZ());benzs.add(new BENZ());go(benzs);ArrayList<Dog> dogs = new ArrayList<>();dogs.add(new Dog());dogs.add(new Dog());dogs.add(new Dog());// go(dogs);}/**所有车比赛*///虽然BMW和BENZ都继承了Car但是 ArrayList<BENZ>, ArrayList<BENZ>,ArrayList< Car>是没有关系的//这时BWM和BENZ是不能同时调用go()的public static void go(ArrayList< Car> cars){}//于是出现了以下的解决方法,通配符?,但是此时的写法,定义的Dog也可以调用go()方法参加比赛public static void go(ArrayList<?> cars){}//所以出现以下正确的写法-泛型上限,必须是Car或者子类才能调用go()方法public static void go(ArrayList<? extends Car> cars){}
}class Dog{}class BENZ extends Car{}class BMW extends Car{}// 父类
class Car{}

? extends Car: ?必须是Car或者其子类 ,泛型上限
? super Car : ?必须是Car或者其父类,泛型下限


5.Set(HashSet,LInkedHashSet,TreeSet)

HashSet:无序,不重复,无索引,LInkedHashSet:有序.不重复,无索引
TreeSet:按照大小默认升序排序,不重复,无索引所以不能使用普遍for循环遍历,也不能用索引来获取元素

1、HashSet(底层采取哈希表存储数据)哈希表是增删改查性能较好的结构

JDK8之前,底层使用数组+链表组成
JDK之后,底层采用数组+链表+红黑树组成




2、LInkedHashSet有序(HashSet的子类,底层依然是哈希表,只是每个元素又额外的多了一个双链表的机制记录存储的顺序)

3、TreeSet可排序(默认从小到大排序,底层基于红黑树的数据结构实现排序的)

示例代码-自定义比较规则-如果TreeSet集合存储的对象有实现比较规则,集合也自带比较器,默认使用集合自带的比较器排序

//方式一:让自定义类实现Comparable接口,重写里面的compareTo方法来定制比较规则
public class Apple implements Comparable<Apple>{private String name;private String color;private double price;private int weight;public Apple() {}public Apple(String name, String color, double price, int weight) {this.name = name;this.color = color;this.price = price;this.weight = weight;}
....
....
....@Overridepublic int compareTo(Apple o) {// 按照重量进行比较的return this.weight - o.weight ; // 去重重量重复的元素// return this.weight - o.weight >= 0 ? 1 : -1; // 保留重量重复的元素}
}
}//方式二:TreeSet集合有参数构造器,可以设置Comparator接口对应的比较器对象来制定比较规则Set<Apple> apples = new TreeSet<>(new Comparator<Apple>() {@Overridepublic int compare(Apple o1, Apple o2) {// return o1.getWeight() - o2.getWeight(); // 升序// 注意:浮点型建议直接使用Double.compare进行比较(内部已经写好比较规则了)return Double.compare(o1.getPrice() , o2.getPrice()); // 升序}});//Lambda省略写法Set<Apple> apples = new TreeSet<>(( o1,  o2) ->  Double.compare(o2.getPrice() , o1.getPrice())  );

Collection大总结


6.Collections(集合工具类)

Collections并不属于集合,是用来操作集合的工具类


示例代码

 Collections.addAll(list, 12, 23, 2, 4);Collections.sort(apples, ( o1,  o2) ->  Double.compare(o1.getPrice() , o2.getPrice()) );

案例-斗地主游戏

示例代码

/
public class Card {private String size;private String color;private int index; // 牌的真正大小public Card(){}public Card(String size, String color, int index) {this.size = size;this.color = color;this.index = index;}
...
...@Overridepublic String toString() {return size + color;}
}/public class GameDemo {/**1、定义一个静态的集合存储54张牌对象*///多态的定义方式public static List<Card> allCards = new ArrayList<>();/**2、做牌:定义静态代码块初始化牌数据*/static {// 3、定义点数:个数确定,类型确定,使用数组String[] sizes = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};// 4、定义花色:个数确定,类型确定,使用数组String[] colors = {"♠", "♥", "♣", "♦"};// 5、组合点数和花色int index = 0; // 记录牌的大小for (String size : sizes) {index++;for (String color : colors) {// 6、封装成一个牌对象。Card c = new Card(size, color, index);// 7、存入到集合容器中去allCards.add(c);}}// 8 大小王存入到集合对象中去 "												

Java学习路线(进阶篇二)相关推荐

  1. Java学习路线·进阶

    Java学习路线是CSDN面向开发者提供系统化「学+练」产品,帮助每一位学习者成为一名优秀的Java工程师. 学习路线系统的涵盖了Java领域内容从初级到进阶所需要学习的一系列「知识点」,内容覆盖Ja ...

  2. Java学习路线!Javacad二次开发

    面试题 如何保证缓存与数据库的双写一致性? 面试官心理分析 你只要用缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问题,那么你如何解决一致性问题? 面试题剖析 一般来 ...

  3. Java入门-Java学习路线课程面试篇:取商 / 和取余(模) % 符号的使用

    本博客地址 | GitHub | 更多资源免费下载 取商 / 和取余(模) % 符号的使用 文章目录 1. / % 最容易出错的演示案例 2. 运行结果: 1. / % 最容易出错的演示案例 pack ...

  4. 给学弟学妹肝的一篇Java学习路线,保证学弟学妹们大三大四的时候顺利找到实习 Offer

    写在开头的闲言碎语 2020年过去了,对很多人来说,这一年经历了太多太多,可能是十年来记忆里比较浓墨重彩的一笔.过去的一年里,"熬"算是这个阶段我的关键字,确实太多时候就要放弃,好 ...

  5. Java学习星球,Java学习路线

    目录 一.Java学习路线 二.学习计划 三.为何会有Java学习星球? 四.加入星球后,你可以得到什么? 五.如何加入Java学习星球? 六.打卡挑战 大家好,我是哪吒,一个靠着热情攀登至C站巅峰的 ...

  6. java学习路线规划

    java学习路线规划 一.写在前面 兄弟,我整理了一下关于自己之前学习java的一些方向,给你归纳在这里,有空就来看看,希望对你有帮助. 二.java基础篇 1.认识java ​ 了解java历史,大 ...

  7. 【最新版】Java学习路线(含B站口碑推荐视频链接)

    文章目录 关于如何自学 一.计算机网络 二.数据结构与算法 三.操作系统 四.计算机组成原理 五.编译原理 六.设计模式 七.MySQL 八.实操工具 九.JAVA并发与JVM 十.Redis 十一. ...

  8. 这可能是最全面的Java学习路线了

    大家好,我是大彬~ 我本科学的不是计算机,大四开始自学Java,并且拿到了几个互联网中大厂的offer.在学习Java这方面还是比较有经验的,下面我来分享下我整理的Java自学路线. 在这里也提醒学弟 ...

  9. JAVA学习路线资料

    java学习路线资料 该博客是摘自其它博主整理的文章,感觉各种视频和书籍链接整理的十分全面,对于初学者来说方便,打算依照博主的架构了解下JAVA开发.虽然主要做嵌入式方面,但了解下JAVA编程也有利于 ...

  10. 人类高质量 Java 学习路线【一条龙版】

    大家好,我是张讨嫌.现在网上的编程资料实在太多了,而且人人肯定都说自己的最好,那就导致大家又不知道怎么选了.大部分的博主推荐资源,也就是把播放量高的视频说一遍,水一期视频,没有一条很清晰的学习路线. ...

最新文章

  1. 只有程序员才能看懂的30张图,绝配!
  2. 《网站分析师实战指南》一2.6 让例行公事的报告见鬼去吧
  3. python常用内置模块-Python内置模块和第三方模块
  4. Oulipo(kmp算法)
  5. 《深入理解java虚拟机》笔记2——GC算法与内存分配策略
  6. NHibernate快速起步
  7. python中json模块博客园_python的json模块
  8. spring boot 使用视图modelandview
  9. android t跳转到fragment,Android 使用EventBus进行Fragment和Activity通信
  10. FastDFS介绍与安装配置
  11. C语言随机读写数据文件(一)
  12. mysql所有版本介绍_MySQL各版本介绍
  13. windows bat定时重启软件
  14. matlab 固态 机械_新手熟知固态硬盘和机械硬盘的区别
  15. SQLite3下载与安装
  16. 其实 Gradle Transform 就是个纸老虎 —— Gradle 系列(4)
  17. [ChneChen的随笔]中国文化清单上我们还记得什么
  18. 苹果关闭iOS 16.1.2 验证通道,iPhone升级 iOS 16.2 后无法降级
  19. [会员积分运营了解]各大主流电商平台会员及积分体系概况集合!
  20. 初学GWT-安装GWT

热门文章

  1. k折交叉验证python代码_K折交叉验证法原理及python实现
  2. 第三方支付转账的法律风险:仅凭支付凭证 不能认定借款关系!
  3. Penetration Test 渗透测试
  4. 一文搞懂NCBI Blast本地数据库(NT/NR等)构建
  5. 利用EXCEL设计JJ斗地主的比赛模式
  6. overflow属性的简单介绍
  7. Signing package index... Cannot open file '/home/jello/openwrt/key-build' for reading
  8. ElementUI Tab 右边加按钮
  9. MonoPort翻译解读 ECCV2020
  10. PowerCLI 通过vCenter批量更改所有的esxi主机名称和DNS