首页
统计
友链
关于
Search
1
静静地生活着
415 阅读
2
JVM_1.引言
404 阅读
3
Chapter 03
331 阅读
4
机器学习 01
323 阅读
5
欢迎使用 Typecho
283 阅读
Java
School
ML
Other
Share
Explore
运维
登录
Search
bbchen
累计撰写
53
篇文章
累计收到
5
条评论
首页
栏目
Java
School
ML
Other
Share
Explore
运维
页面
统计
友链
关于
搜索到
53
篇与
的结果
2023-02-26
Chapter23_反射
反射(Reflection)反射机制反射机制允许程序再执行期间 借助于 Reflection API 取得任何类的内部消息(比如成员变量、构造器、成员方法等等),并能操作对象的属性及方法。反射在设计模式和框架底层都会用到加载完类之后,在堆中就产生了一个 Class 类型的对象(一个类只有一个Class 对象),这个对象包含了类的完整结构信息。通过这个对象得到类的结构,这个对象就像一面镜子,透过这个镜子看到类的结构,所以形象的称之为:反射Java反射机制原理图反射机制可以完成在运行时判断任意一个对象所属的类在运行时构造任意一个类的对象在运行时得到任意一个类所具有的成员变量和方法在运行时调用任意一个对象的成员变量和方法生成动态代理反射相关的主要类java.lang.Class:代表一个类,Class对象表示某个类加载后在堆中的对象java.lang.reflect.Method:代表类的方法java.lang.reflect.Field:代表类的成员变量java.lang.reflect.Cdnstructor:代表类的构造方法Class 类Class 类也是类,因此也继承Object类Class 类对象不是 new 出来的,而是系统创建的对于某个类的Class 类对象,而内存中只有一份,因此类只加载一次每个类的实例都会记得自己是由哪个 Class 实例所生成通过 Class 可以完整地得到一个类的完整结构,通过一系列 APIClass 对象是存放在堆的类的字节码二进制数据,是存放在方法区的,有的地方称为类的元数据(包括 方法代码,变量名,方法名,访问权限等等)常用方法package com.bbedu.reflection.class_; import com.bbedu.Car; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; /** * Class类的常用方法 */ public class Class02 { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException { String classAllPath = "com.bbedu.Car"; // <?> 表示不确定的Java类型 Class<?> cls = Class.forName(classAllPath); // 输出cls System.out.println(cls); // 显示cls对象是哪个类的Class对象 class com.bbedu.Car System.out.println(cls.getClass()); // class java.lang.Class // 得到包名 System.out.println(cls.getPackage().getName()); // com.bbedu // 得到全类名 System.out.println(cls.getName()); // com.bbedu.Car // 通过cls创建对象实例 Car car = (Car) cls.getDeclaredConstructor().newInstance(); System.out.println(car); // 通过反射获取属性 Field brand = cls.getField("brand"); System.out.println(brand.get(car)); // 给属性赋值 brand.set(car, "benz"); System.out.println(brand.get(car)); // 获取所有字段 System.out.println("=======所有字段属性========"); Field[] fields = cls.getFields(); for (int i = 0; i < fields.length; i++) { System.out.println(fields[i].getName()); } } }获取 Class 对象的六种方式前提:已知一个类的全类名,且该类在类路径下,可以通过 Class 类的静态方法 forName() 获取,可能抛出 ClassNotFoundException应用场景:多用于配置文件,读取类全路径,加载类package com.bbedu.reflection.class_; import com.bbedu.Car; /** * 获取 Class 对象的各种方式(6) */ public class GetClass_ { public static void main(String[] args) throws ClassNotFoundException { // 1.Class.forName String classAllPath = "com.bbedu.Car"; Class<?> cls1 = Class.forName(classAllPath); System.out.println(cls1); // 2.类名.class Class<Car> cls2 = Car.class; System.out.println(cls2); // 3.对象.getClass() Car car = new Car(); Class cls3 = car.getClass(); System.out.println(cls3); // 4.通过类加载器[4种] ClassLoader classLoader = car.getClass().getClassLoader(); Class cls4 = classLoader.loadClass(classAllPath); System.out.println(cls4); System.out.println(cls1.hashCode()); System.out.println(cls2.hashCode()); System.out.println(cls3.hashCode()); System.out.println(cls4.hashCode()); // 5.基本数据类型 Class<Integer> integerClass = int.class; Class<Character> characterClass = char.class; Class<Boolean> booleanClass = boolean.class; System.out.println(integerClass); // 6.基本数据类型对应的包装类 Class<Integer> type = Integer.TYPE; System.out.println(type); Class<Character> type1 = Character.TYPE; System.out.println(type1); System.out.println(integerClass.hashCode()); System.out.println(type.hashCode()); } }哪些类型有 Class 对象package com.bbedu.reflection.class_; import java.io.Serializable; /** * 那些类型有 Class 对象 */ public class AllTypeClass { public static void main(String[] args) { Class<String> cls1 = String.class; Class<Serializable> cls2 = Serializable.class; Class<Integer[]> cls3 = Integer[].class; Class<Integer[][]> cls4 = Integer[][].class; Class<Deprecated> cls5 = Deprecated.class; Class<Thread.State> cls6 = Thread.State.class; Class<Long> cls7 = long.class; Class<Void> cls8 = void.class; Class<Class> cls9 = Class.class; System.out.println(cls1); System.out.println(cls2); System.out.println(cls3); System.out.println(cls4); System.out.println(cls5); System.out.println(cls6); System.out.println(cls7); System.out.println(cls8); System.out.println(cls9); } }类加载反射机制是 java 实现动态语言的关键,也就是通过反射实现类动态加载静态加载:编译时加载相关的类,如果没有则报错,依赖性太强动态加载:运行时夹杂i需要的累,如果运行时不用该类,则不报错,降低了依赖性类加载过程图加载阶段JVM 在该阶段的主要目的是将字节码从不同的数据源(可能是 class 文件、也可能是 jar 包,甚至网络) 转化位二进制数据加载到内存中,并生成一个代表该类的 java.lang.Class 对象链接阶段-验证-准备-解析虚拟机将常量池内的符号引用替换为直接引用的过程初始化获取类的结构信息package com.bbedu.reflection; import org.junit.jupiter.api.Test; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; /** * 通过反射获取类的结构信息 */ public class ReflectionUtils { public static void main(String[] args) { } // 第一组 @Test public void api_01() throws ClassNotFoundException { Class<?> personCls = Class.forName("com.bbedu.reflection.Person"); // 全类名 com.bbedu.reflection.Person System.out.println(personCls.getName()); // 简单类名 Person System.out.println(personCls.getSimpleName()); // 获取所有public属性,包含本类和父类 Field[] fields = personCls.getFields(); for (Field field : fields) { System.out.println("本类及父类的属性:" + field.getName()); } // 所有属性 Field[] declaredFields = personCls.getDeclaredFields(); for (Field declaredField : declaredFields) { System.out.println("本类所有属性:" + declaredField.getName()); } // 本类及父类的public方法 Method[] methods = personCls.getMethods(); for (Method method : methods) { System.out.println("本类及父类的方法:" + method.getName()); } // 本类所有方法 Method[] declaredMethods = personCls.getDeclaredMethods(); for (Method declaredMethod : declaredMethods) { System.out.println("本类所有方法:" + declaredMethod.getName()); } // 获取本类的public构造器 /** * Returns: * the array of Constructor objects representing the public constructors of this class */ Constructor<?>[] constructors = personCls.getConstructors(); for (Constructor<?> constructor : constructors) { System.out.println("本类的构造器:" + constructor.getName()); } // 获取所有构造器 Constructor<?>[] declaredConstructors = personCls.getDeclaredConstructors(); for (Constructor<?> declaredConstructor : declaredConstructors) { System.out.println("本类所有构造器:" + declaredConstructor.getName()); } // 获取包信息 System.out.println(personCls.getPackage()); // 返回父类信息 Class<?> superclass = personCls.getSuperclass(); System.out.println(superclass); System.out.println(superclass.getSuperclass()); // 得到接口信息 Class<?>[] interfaces = personCls.getInterfaces(); for (Class<?> anInterface : interfaces) { System.out.println("接口信息" + anInterface); } // 注解信息 Annotation[] annotations = personCls.getAnnotations(); for (Annotation annotation : annotations) { System.out.println("注解信息" + annotation); } } } class A { public String hobby; public A() { } public void hi() { } } interface IA { } interface IB { } @Deprecated() class Person extends A implements IA, IB { // 属性 public String name; protected int age; String job; private double sal; public Person() { } public Person(String name) { } private Person(String name, int age) { } // 方法 public void m1() { } protected void m2() { } void m3() { } private void m4() { } } 反射爆破创建实例package com.bbedu.reflection; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; public class ReflectionCreateInstance { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { // 获取Class对象 Class<?> cls = Class.forName("com.bbedu.reflection.User"); // 1.通过public的无参构造器创建实例 Object o = cls.newInstance(); System.out.println(o); // 2.通过public的有参构造器创建实例 // 2.1 得到构造器 Constructor<?> constructor = cls.getConstructor(String.class); // 2.2 创建实例 Object o1 = constructor.newInstance("hello"); System.out.println(o1); // 私有构造器 /*Returns: the Constructor object of the public constructor that matches the specified parameterTypes*/ // Constructor<?> constructor1 = cls.getConstructor(int.class, String.class); Constructor<?> declaredConstructor = cls.getDeclaredConstructor(int.class, String.class); // 暴破(暴力破解),使用反射可以访问private构造器 // 反射面前,都是纸老虎 declaredConstructor.setAccessible(true); Object emmm = declaredConstructor.newInstance(20, "emmm"); System.out.println(emmm); } } class User { private int age = 10; private String name = "bbchen"; public User() { } public User(String name) { this.name = name; } private User(int age, String name) { this.age = age; this.name = name; } @Override public String toString() { return "User{" + "age=" + age + ", name='" + name + '\'' + '}'; } }操作属性package com.bbedu.reflection; import java.lang.reflect.Field; /** * 反射操作属性 */ public class ReflectionAccessProperty { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException { Class<?> cls = Class.forName("com.bbedu.reflection.Student"); Object o = cls.newInstance(); System.out.println(o.getClass()); Field age = cls.getField("age"); System.out.println(o); age.set(o, 99); System.out.println(o); System.out.println(age.get(o)); Field name = cls.getDeclaredField("name"); // 暴破 name.setAccessible(true); // name.set(o, "Siri"); // static 属性,因此可以写成null name.set(null, "Siri"); System.out.println(name.get(o)); System.out.println(name.get(o)); } } class Student { public int age; private static String name; public Student() { } @Override public String toString() { return "Student{" + "age=" + age + ", name=" + name + '}'; } }操作方法package com.bbedu.reflection; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * 反射调用方法 */ public class ReflectionAccessMethod { public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { Class<?> cls = Class.forName("com.bbedu.reflection.Boss"); Object o = cls.newInstance(); // Method hi = cls.getMethod("hi", String.class); Method hi = cls.getDeclaredMethod("hi", String.class); hi.invoke(o, "bbchen"); Method say = cls.getDeclaredMethod("say", int.class, String.class, char.class); // 暴破 say.setAccessible(true); System.out.println(say.invoke(o, 123, "hello", 'm')); // 静态方法还可以这样 System.out.println(say.invoke(null, 123, "hello", 'm')); Object invoke = say.invoke(o, 123, "hello", 'm'); System.out.println(invoke.getClass()); System.out.println(invoke); } } class Boss { public int age; private static String name; public Boss() { } private static String say(int n, String s, char c) { return n + " " + s + " " + c; } public void hi(String s) { System.out.println("hi " + s); } }
2023年02月26日
41 阅读
0 评论
0 点赞
2023-02-26
Chapter18_IO流
多线程初步概念程序是为了完成特定任务,用某种语言编写的一组指令的集合进程进程是运行中的程序,比如我们使用 QQ,就启动了一个进程,操作系统就会为该进程分配内存空间,当我们使用微信,有启动了一个进程,操作系统将为微信分配新的内存空间进程是程序的一次执行过程,或是正在运行的一个程序,是动态过程,有它自身的产生、存在和消亡的过程线程线程是由进程创建的,是进程的一个实体一个进程可以拥有多个线程单线程同一个时刻,只允许执行一个线程多线程同一个时刻,可以执行多个线程并发同一个时刻,多个任务交替执行,造成一种“貌似同时”的错觉,简单来说,单核 CPU 是实现的多任务就是并发并行同一个时刻,多个任务同时执行,多核 CPU 可以实现并行线程基本使用继承 Thread 类, 重写 run 方法实现 Runnable 接口,重写 run 方法真正实现多线程效果的,是start0(),而不是 run()package com.bbedu.threadUse; public class Thread03 { public static void main(String[] args) { Thread thread1 = new Thread(new T1()); Thread thread2 = new Thread(new T2()); thread1.start(); thread2.start(); } } class T1 implements Runnable { int count = 0; @Override public void run() { while (true) { System.out.println("hello~ " + (++count)); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } if (count == 30) { break; } } } } class T2 implements Runnable { int count = 0; @Override public void run() { while (true) { System.out.println("hi~ " + (++count)); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } if (count == 40) { break; } } } }Thread 和 Runnable 的区别线程常用方法练习package com.bbedu.method; public class ThreadMethodExercise { public static void main(String[] args) throws InterruptedException { T2 t2 = new T2(); for (int i = 1; i <= 10; i++) { System.out.println("hi " + i); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } if (i == 5) { t2.start(); t2.join(); } } System.out.println("主线程结束..."); } } class T2 extends Thread{ int num = 0; @Override public void run() { while (num < 10) { System.out.println("hello " + (++num)); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("子线程结束..."); } }线程七大状态Synchronized互斥锁Java语言中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。每个对象都对应于一个可称为“互斥锁”的标记,这个标记用来保证在任一时刻,能有一个线程访问该对象。关键字synchronized来与对象的互斥锁联系。当某个对象 synchronized 修饰时,表明该对象在任一时刻只能由一个线程访问同步的局限性:导致程序的执行效率要降低同步方法(非静态的)的锁可以是this,也可以是其他对象(要求是同一个对象)同步方法(静态的)的锁为当前类本身。细节同步方法如果没有使用static修饰:默认锁对象为this如果方法使用static修饰,默认锁对象:当前类.class实现的落地步骤:需要先分析上锁的代码选择同步代码块或同步方法要求多个线程的锁对象为同一个即可!作业package com.bbedu.homework; import java.util.Map; import java.util.Random; import java.util.Scanner; public class Homework01 { public static void main(String[] args) { T01 t01 = new T01(); T02 t02 = new T02(t01); t01.start(); t02.start(); } } class T01 extends Thread { private boolean loop = true; @Override public void run() { while (loop) { System.out.println((int)(Math.random() * 100 + 1)); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } public void setLoop(boolean loop) { this.loop = loop; } } class T02 extends Thread { private T01 t01; private Scanner scanner = new Scanner(System.in); public T02(T01 t01) { this.t01 = t01; } @Override public void run() { while (true) { System.out.println("输入q结束"); char c = scanner.next().toUpperCase().charAt(0); if (c == 'Q') { t01.setLoop(false); System.out.println("t01退出"); break; } } } }package com.bbedu.homework; public class Homework02 { public static void main(String[] args) { Withdraw withdraw = new Withdraw(); Thread thread1 = new Thread(withdraw); Thread thread2 = new Thread(withdraw); thread1.start(); thread2.start(); } } class Withdraw implements Runnable { static final Object obj = new Object(); private static int total = 10000; private boolean loop = true; public void withdraw() { synchronized (obj) { if (total <= 0) { loop = false; return; } total -= 1000; System.out.println("用户 " + Thread.currentThread().getName() + " 取出1000元" + " 剩余=" + total); } } @Override public void run() { while (loop) { withdraw(); try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } } }
2023年02月26日
30 阅读
0 评论
0 点赞
2023-02-26
Chapter17_多线程
多线程初步概念程序是为了完成特定任务,用某种语言编写的一组指令的集合进程进程是运行中的程序,比如我们使用 QQ,就启动了一个进程,操作系统就会为该进程分配内存空间,当我们使用微信,有启动了一个进程,操作系统将为微信分配新的内存空间进程是程序的一次执行过程,或是正在运行的一个程序,是动态过程,有它自身的产生、存在和消亡的过程线程线程是由进程创建的,是进程的一个实体一个进程可以拥有多个线程单线程同一个时刻,只允许执行一个线程多线程同一个时刻,可以执行多个线程并发同一个时刻,多个任务交替执行,造成一种“貌似同时”的错觉,简单来说,单核 CPU 是实现的多任务就是并发并行同一个时刻,多个任务同时执行,多核 CPU 可以实现并行线程基本使用继承 Thread 类, 重写 run 方法实现 Runnable 接口,重写 run 方法真正实现多线程效果的,是start0(),而不是 run()package com.bbedu.threadUse; public class Thread03 { public static void main(String[] args) { Thread thread1 = new Thread(new T1()); Thread thread2 = new Thread(new T2()); thread1.start(); thread2.start(); } } class T1 implements Runnable { int count = 0; @Override public void run() { while (true) { System.out.println("hello~ " + (++count)); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } if (count == 30) { break; } } } } class T2 implements Runnable { int count = 0; @Override public void run() { while (true) { System.out.println("hi~ " + (++count)); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } if (count == 40) { break; } } } }Thread 和 Runnable 的区别线程常用方法练习package com.bbedu.method; public class ThreadMethodExercise { public static void main(String[] args) throws InterruptedException { T2 t2 = new T2(); for (int i = 1; i <= 10; i++) { System.out.println("hi " + i); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } if (i == 5) { t2.start(); t2.join(); } } System.out.println("主线程结束..."); } } class T2 extends Thread{ int num = 0; @Override public void run() { while (num < 10) { System.out.println("hello " + (++num)); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("子线程结束..."); } }线程七大状态Synchronized互斥锁Java语言中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。每个对象都对应于一个可称为“互斥锁”的标记,这个标记用来保证在任一时刻,能有一个线程访问该对象。关键字synchronized来与对象的互斥锁联系。当某个对象 synchronized 修饰时,表明该对象在任一时刻只能由一个线程访问同步的局限性:导致程序的执行效率要降低同步方法(非静态的)的锁可以是this,也可以是其他对象(要求是同一个对象)同步方法(静态的)的锁为当前类本身。细节同步方法如果没有使用static修饰:默认锁对象为this如果方法使用static修饰,默认锁对象:当前类.class实现的落地步骤:需要先分析上锁的代码选择同步代码块或同步方法要求多个线程的锁对象为同一个即可!作业package com.bbedu.homework; import java.util.Map; import java.util.Random; import java.util.Scanner; public class Homework01 { public static void main(String[] args) { T01 t01 = new T01(); T02 t02 = new T02(t01); t01.start(); t02.start(); } } class T01 extends Thread { private boolean loop = true; @Override public void run() { while (loop) { System.out.println((int)(Math.random() * 100 + 1)); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } public void setLoop(boolean loop) { this.loop = loop; } } class T02 extends Thread { private T01 t01; private Scanner scanner = new Scanner(System.in); public T02(T01 t01) { this.t01 = t01; } @Override public void run() { while (true) { System.out.println("输入q结束"); char c = scanner.next().toUpperCase().charAt(0); if (c == 'Q') { t01.setLoop(false); System.out.println("t01退出"); break; } } } }package com.bbedu.homework; public class Homework02 { public static void main(String[] args) { Withdraw withdraw = new Withdraw(); Thread thread1 = new Thread(withdraw); Thread thread2 = new Thread(withdraw); thread1.start(); thread2.start(); } } class Withdraw implements Runnable { static final Object obj = new Object(); private static int total = 10000; private boolean loop = true; public void withdraw() { synchronized (obj) { if (total <= 0) { loop = false; return; } total -= 1000; System.out.println("用户 " + Thread.currentThread().getName() + " 取出1000元" + " 剩余=" + total); } } @Override public void run() { while (loop) { withdraw(); try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } } } }
2023年02月26日
47 阅读
0 评论
0 点赞
2023-02-26
Chapter15_泛型
泛型泛型的理解和好处编译时,检查添加元素的类型,提高了安全性减少了类型转换的次数,提高效率不再提示编译警告package com.bbedu.generic.improve; import java.util.ArrayList; public class Generic02 { public static void main(String[] args) { // 这样写时,ArrayList<Dog> 表示存放到集合中的元素是 Dog 类型 // 如果添加类型不满足要求,编译器会报错 // 相当于加入约束 // 在遍历时,可以直接取出 Dog 类型,而不是 Object ArrayList<Dog> arrayList = new ArrayList<Dog>(); arrayList.add(new Dog("旺财", 10)); arrayList.add(new Dog("发财", 5)); arrayList.add(new Dog("大黄", 6)); // 放入猫 //arrayList.add(new Cat("招财猫", 3)); for (Dog dog:arrayList) { System.out.println(dog.getName()+ "-" + dog.getAge()); } } } class Dog { private String name; private int age; public Dog(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; } } class Cat{ private String name; private int age; public Cat(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; } }泛型介绍泛型又称参数化类型,是 jdk5.0 出现的新特性,解决数据类型的安全性问题在类声明或实例化时只要指定好需要的具体的类型即可Java 泛型可以保证如果程序在编译时没有翻出警告,运行时就不会产生 ClassCastException 异常,同时,代码更加简洁、健壮泛型的作用是:可以在类声明时通过一个标识表示类中某个属性的类型,或者是某个方法的返回值的类型,或者是参数类型泛型的语法声明interface 接口<T>{} 和 class 类<K, V>{}说明:其中,T,K,V不代表值,而是表示类型任意字母都可以,常用 T 表示,short of Type实例化要在类名后面指定类型参数的值(类型),如:List<String> strList = new ArrayList<String>();Iterator<Customer> iterator = customers.iterator();细节interface List<T>{}, public class HashSet<E>{}...说明:T,E只能是引用类型在给泛型指定具体类型后,可以传入该类型或该类型的子类型泛型的使用形式List<Integer> list1 = new ArrayList<Integer>();可简化为:// 编译器会进行类型推断,推荐这种写法:List<Integer> list2 = new ArrayList<>();如果是这样写:ArrayList arrayList = new ArrayList();等价于:ArrayList<Object> arrayList = new ArrayList<>();练习 p560package com.bbedu.generic.exercise; import java.util.ArrayList; import java.util.Comparator; import java.util.Objects; public class Exercise01 { public static void main(String[] args) { Employee jack = new Employee("Jack", 20000, new MyDate(1999, 1, 1)); Employee jack2 = new Employee("Jack", 25000, new MyDate(1999, 1, 2)); Employee mike = new Employee("Mike", 15000, new MyDate(2000, 2, 6)); Employee sam = new Employee("Sam", 30000, new MyDate(1989, 10, 1)); Employee tim = new Employee("Tim", 10000, new MyDate(2002, 4, 1)); Employee tim2 = new Employee("Tim", 10000, new MyDate(2001, 4, 1)); ArrayList<Employee> employees = new ArrayList<>(); employees.add(sam); employees.add(jack2); employees.add(jack); employees.add(mike); employees.add(tim); employees.add(tim2); System.out.println("===排序前==="); System.out.println(employees); employees.sort(new Comparator<Employee>() { @Override public int compare(Employee o1, Employee o2) { if(!(o1 instanceof Employee && o2 instanceof Employee)){ System.out.println("类型不正确..."); return 0; } if(o1.getName().compareTo(o2.getName()) != 0){ return o1.getName().compareTo(o2.getName()); } // 封装提升可维护性和复用性 return o1.getBirthday().compareTo(o2.getBirthday()); } }); System.out.println("===排序后==="); System.out.println(employees); } } class Employee { private String name; private double sal; private MyDate birthday; public Employee(String name, double sal, MyDate birthday) { this.name = name; this.sal = sal; this.birthday = birthday; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getSal() { return sal; } public void setSal(double sal) { this.sal = sal; } public MyDate getBirthday() { return birthday; } public void setBirthday(MyDate birthday) { this.birthday = birthday; } @Override public String toString() { return "Employee{" + "name='" + name + '\'' + ", sal=" + sal + ", birthday=" + birthday + '}' + "\n"; } } class MyDate implements Comparable<MyDate>{ private int year; private int month; private int day; public MyDate(int year, int month, int day) { this.year = year; this.month = month; this.day = day; } public int getYear() { return year; } public void setYear(int year) { this.year = year; } public int getMonth() { return month; } public void setMonth(int month) { this.month = month; } public int getDay() { return day; } public void setDay(int day) { this.day = day; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; MyDate myDate = (MyDate) o; return year == myDate.year && month == myDate.month && day == myDate.day; } @Override public int hashCode() { return Objects.hash(year, month, day); } @Override public String toString() { return "MyDate{" + "year=" + year + ", month=" + month + ", day=" + day + '}'; } @Override public int compareTo(MyDate o) { int yearMinus = year - o.getYear(); if(yearMinus != 0){ return yearMinus; } int monthMinus = month - o.month; if (monthMinus != 0) { return monthMinus; } return day - o.day; } }自定义泛型泛型类普通成员可以使用泛型(属性、方法)使用泛型的数组,不能初始化静态方法中不能使用类的泛型泛型类的类型,是在创建对象时确定的(因为创建对象时,需要指定确定类型)如果在创建对象时,没有指定类型,默认为Object泛型接口接口中,静态成员不能使用泛型泛型接口的类型,是在继承接口或者实现接口时实现的没有指定类型时,默认为 Object泛型方法基本语法:修饰符 <T, R> 返回方法 方法名(参数列表) {}泛型方法,可以定义在普通类中,也可以定义在泛型类中当泛型方法被调用时,类型也会被确定修饰符 返回方法 方法名(参数列表){}不是泛型方法,是使用了泛型的方法泛型继承和通配符泛型没有继承机制例如:List list = new ArrayList(); // 错误<?>: 支持任意类型的泛型<? extend AA> : 表示上限,可以接收 AA 或 AA 的子类<? super AA>: 表示下限,可以接收 AA 或 AA 的父类本章作业JUnit一个类有很多功能代码需要测试,为了测试,就需要写到 main 方法中如果有多个功能代码测试,就需要来回注销,切换很麻烦如果可以直接运行一个方法,就方便很多,并且可以给出相关信息 -> JUnitpackage com.bbedu.generic.homework; import org.junit.jupiter.api.Test; import java.util.*; public class Homework01 { @Test public void testList() { DAO<User> dao = new DAO<>(); dao.save("001", new User(1, 10, "Jack")); dao.save("002", new User(2, 12, "Tom")); dao.save("003", new User(3, 14, "Mary")); System.out.println(dao.list()); dao.update("003", new User(3, 23, "Milan")); System.out.println(dao.list()); dao.delete("001"); System.out.println(dao.list()); System.out.println(dao.get("003")); } } class DAO<T> { private Map<String, T> map = new HashMap<>(); public T get(String id) { return map.get(id); } public void update(String id, T entity) { map.put(id, entity); } public List<T> list() { List<T> list = new ArrayList<>(); Set<String> strings = map.keySet(); for (String string : strings) { list.add(get(string)); } return list; } public void delete(String id) { map.remove(id); } public void save(String id, T entity) { map.put(id, entity); } } class User { private int id; private int age; private String name; public User(int id, int age, String name) { this.id = id; this.age = age; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "User{" + "id=" + id + ", age=" + age + ", name='" + name + '\'' + '}'; } }
2023年02月26日
44 阅读
0 评论
0 点赞
2023-02-26
Chapter14_集合
集合集合的框架体系CollectionCollection 接口实现类的特点public interface Collection extends Iterablecollection 实现子类可以存放多个元素,每个元素可以是 Object有些 Collection 的实现类,可以存放重复的元素,有些不可以Collection 的实现类,有些是有序的(List),有些不是有序的(Set)Collection 接口没有直接实现子类,是通过它的子接口 Set 和 List 来实现的常用方法package com.bbedu.collection_; import java.util.ArrayList; import java.util.List; @SuppressWarnings({"all"}) public class CollectionMethod { public static void main(String[] args) { List list = new ArrayList(); // add list.add("Tim"); list.add(10); // 相当于list.add(new Integer(10)) list.add(true); System.out.println("list=" + list); // remove list.remove(0); // 删除第一个元素 list.remove((Integer) 10); System.out.println("list=" + list); // contains System.out.println(list.contains(true)); // size System.out.println(list.size()); // isEmpty System.out.println(list.isEmpty()); // clear list.clear(); System.out.println("list=" + list); // addAll ArrayList list2 = new ArrayList(); list2.add("红楼梦"); list2.add("三国演义"); list.addAll(list2); System.out.println("list=" + list); // containsAll System.out.println(list.containsAll(list2)); // removeAll list.add("Macbeth"); list.removeAll(list2); System.out.println("list=" + list); } }迭代器遍历Iterable 类中,可以返回一个 Iterator 对象,迭代器,可以用来遍历Iterator对象称为迭代器,主要用于遍历Collection集合中的元素。所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了lterator接口的对象,即可以返回一个迭代器。lterator的结构:Iterator仅用于遍历集合,Iterator本身并不存放对象。增强 for 循环增强 for 循环,可以替代 iterator 迭代器,特点:增强 for 就是简化版的 iterator,本质相同。但只能用于遍历集合和数组基本语法:for(元素类型 元素名 : 集合名或数组名){ 访问元素;}练习package com.bbedu.collection_; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class CollectionExercise { public static void main(String[] args) { List<Dog> dogs = new ArrayList<>(); Dog dog1 = new Dog("小黑", 3); Dog dog2 = new Dog("大黄", 5); Dog dog3 = new Dog("旺财", 6); dogs.add(dog1); dogs.add(dog2); dogs.add(dog3); Iterator<Dog> iterator = dogs.iterator(); System.out.println("=====迭代器====="); while (iterator.hasNext()) { Dog next = iterator.next(); System.out.println(next); } System.out.println("=====增强for循环====="); for (Dog dog : dogs) { System.out.println(dog); } } } class Dog { private String name; private int age; public Dog(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; } @Override public String toString() { return "Dog{" + "name='" + name + '\'' + ", age=" + age + '}'; } }List 接口基本介绍List 接口是 Collection 接口的子接口List集合类中元素有序(即添加顺序和取出顺序一致)、且可重复List集合中的每个元素都有其对应的顺序索引,即支持索引List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素常用方法package com.bbedu.list_; import java.util.ArrayList; import java.util.List; public class ListMethod { public static void main(String[] args) { // add ArrayList list = new ArrayList(); list.add("计算机组成原理"); list.add("操作系统"); list.add(1, "数据结构"); // 插入指定位置 System.out.println("list=" + list); // addAll ArrayList list2= new ArrayList(); list2.add("Tim"); list2.add("Mike"); list.addAll(1, list2); System.out.println("list=" + list); // indexOf lastIndexOf System.out.println(list.indexOf("Tim")); list.add("Tim"); System.out.println(list.lastIndexOf("Tim")); // remove list.remove(0); System.out.println("list=" + list); // set 相当于替换 list.set(0, "Jim"); System.out.println("list=" + list); // subList 范围:[fromIndex, toIndex) List retList = list.subList(0, 2); System.out.println("returnList=" + retList); } }List 的三种遍历iterator增强 for普通 for练习package com.bbedu.list_; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Vector; public class ListExercise02 { public static void main(String[] args) { List list = new ArrayList(); // List list = new LinkedList(); // List list = new Vector(); list.add(new Book("红楼梦", 100, "曹雪芹")); list.add(new Book("西游记", 10, "吴承恩")); list.add(new Book("水浒传", 19, "施耐庵")); list.add(new Book("三国演义", 20, "罗贯中")); list.add(new Book("西游记", 10, "吴承恩")); for (Object o : list) { System.out.println(o); } sort(list); System.out.println("=====排序后====="); for (Object o : list) { System.out.println(o); } } public static void sort(List list){ for (int i = 0; i < list.size() - 1; i++) { for (int j = 0; j < list.size() - i - 1; j++) { Book book1 = (Book) list.get(j); Book book2 = (Book) list.get(j + 1); if(book1.getPrice() > book2.getPrice()){ list.set(j, book2); list.set(j+1, book1); } } } } } class Book { private String name; private int price; private String author; public Book(String name, int price, String author) { this.name = name; this.price = price; this.author = author; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getPrice() { return price; } public void setPrice(int price) { this.price = price; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } @Override public String toString() { return "名称:" + name + "\t 价格:" + price + "\t 作者:" + author; } }ArrayList注意事项permits all elements, including nullArrayList 是由数组来实现数据存储的ArrayList 基本等同于 Vector,除了 ArrayList 是线程不安全,在多线程情况下,不建议使用 ArrayList底层结构和源码分析先结论,再源码ArrayList中维护了一个Object类型的数组elementData. [debug 看源码]transient Object[] elementData; //transient表示瞬间,短暂的,表示该属性不会被序列化当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第1次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍。如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData为1.5倍。package com.bbedu.list_; import java.util.ArrayList; import java.util.Vector; public class ArrayListSource { public static void main(String[] args) { ArrayList list = new ArrayList(8); for (int i = 1; i <= 10; i++) { list.add(i); } for (int i = 11; i <= 15; i++) { list.add(i); } list.add(100); list.add(200); list.add(300); } }初始为10:若先指定 ArrayList 大小,底层类似,不再赘述Vector注意事项Vector 类的定义说明Vector 底层也是一个对象数组,protected Object[] elementData;Vector 是线程同步的,即线程安全,Vector 类的操作方法带有 synchronized在开发中,需要线程同步安全时,考虑使用 VectorVector 和 ArrayList 比较扩容源码分析package com.bbedu.list_; import java.util.Vector; @SuppressWarnings({"all"}) public class Vector_ { public static void main(String[] args) { Vector vector = new Vector(); for (int i = 0; i < 10; i++) { vector.add(i); } vector.add(100); } }LinkedListLinkedList 底层实现了双向链表和双向队列特点可以添加任意元素(元素可以重复),包括 null线程不安全,没有实现同步LinkedList 的底层操作机制LinkedList 底层维护了一个双向链表LinkedList 中维护了两个属性 first 和 last 分别指向 首节点和尾节点每个节点(Node对象)里又维护了 prev、next、item 三个属性,其中通过 prev 指向前一个,通过 next 指向后一个节点,最终实现双向链表LinkedList 的元素的添加和删除,不是通过数组完成的,因此效率相对较高package com.bbedu.list_; import java.util.Iterator; import java.util.LinkedList; @SuppressWarnings({"all"}) public class LinkedListCRUD { public static void main(String[] args) { LinkedList linkedList = new LinkedList(); linkedList.add(1); linkedList.add(2); linkedList.add(3); System.out.println("linkedList=" + linkedList); linkedList.remove(); // 默认删除第一个节点 System.out.println("linkedList=" + linkedList); linkedList.set(0, 999); System.out.println("linkedList=" + linkedList); linkedList.get(1); System.out.println(linkedList.get(1)); Iterator iterator = linkedList.iterator(); while (iterator.hasNext()) { Object next = iterator.next(); System.out.println("next=" + next); } for (Object o : linkedList) { System.out.println("o=" + o); } } }jdk底层研究方法类似,请自行研究。ArrayList 和 LinkedList 比较如何选择ArrayList和LinkedList:如果我们改查的操作多,选择ArrayList如果我们增删的操作多,选择LinkedList一般来说,在程序中,80%-90%都是查询,因此大部分情况下会选择ArrayList在一个项目中,根据业务灵活选择,也可能这样,一个模块使用的是ArrayList, 另外一个模块是 LinkedList.Set 接口基本介绍无序(添加和取出的顺序不一致),没有索引不允许重复元素,所以最多包含一个nullJDK API 中 Set 接口的实现类有:常用方法和 List 接口一样,Set 接口也是 Collection 的子接口,因此常用方法和 Collection 接口一样遍历方法同 Collection 的遍历方式一样,因为 Set 接口是 Collection 接口的子接口:可以使用迭代器增强 for 循环不能使用 索引的方式来获取package com.bbedu.set_; import java.util.HashSet; import java.util.Iterator; import java.util.Set; @SuppressWarnings({"all"}) public class SetMethod { public static void main(String[] args) { Set set = new HashSet(); set.add("john"); set.add("lucy"); set.add("john"); set.add("job"); set.add(null); System.out.println("set=" + set); System.out.println("====迭代器===="); Iterator iterator = set.iterator(); while (iterator.hasNext()) { Object next = iterator.next(); System.out.println("next=" + next); } set.remove(null); System.out.println("====增强for===="); for (Object o : set) { System.out.println("o=" + o); } } }HashSetHashSet 实现了 Set 接口HashSet 底层实际上是是 HashMap不能有重复的元素,可以存放 null,但是只能有一个 nullHashSet 不保证元素是有序的,取决于 Hash 后,再确定索引的结果package com.bbedu.set_; import java.util.HashSet; public class HashSet01 { public static void main(String[] args) { HashSet hashSet = new HashSet(); System.out.println(hashSet.add("John")); System.out.println(hashSet.add("Lucy")); System.out.println(hashSet.add("John")); System.out.println(hashSet.add("Jack")); System.out.println(hashSet.add("Tim")); // 指定删除对象 hashSet.remove("John"); System.out.println("set=" + hashSet); hashSet = new HashSet(); System.out.println("set=" + hashSet); hashSet.add("lucy"); hashSet.add("lucy"); hashSet.add(new Dog("coco")); // OK hashSet.add(new Dog("coco")); // OK System.out.println("set=" + hashSet); // 看源码理解 // 不能添加重复元素的真正含义? hashSet.add(new String("bbchen")); // ok hashSet.add(new String("bbchen")); // no System.out.println("set=" + hashSet); } } class Dog { private String name; public Dog(String name) { this.name = name; } @Override public String toString() { return "Dog{" + "name='" + name + '\'' + '}'; } }HashSet 底层机制说明分析 HashSet 底层是 HashMap, HashMap 底层是(数组 + 链表 + 红黑树)数组+链表=邻接表,理解邻接表:package com.bbedu.set_; /** * 模拟邻接表 */ public class HashSetStructure { public static void main(String[] args) { // Node[] 数组 称为 表 Node[] table = new Node[16]; Node john = new Node("john", null); table[2] = john; Node jack = new Node("jack", null); john.next = jack; Node rose = new Node("Rose", null); jack.next = rose; } } class Node { Object item; Node next; public Node(Object item, Node next) { this.item = item; this.next = next; } }分析 HashSet 的添加元素底层是如何实现的同样,先结论,后Debug源码分析:初始化HashSet()/** * Constructs a new, empty set; the backing {@code HashMap} instance has * default initial capacity (16) and load factor (0.75). */ public HashSet() { map = new HashMap<>(); }add()/** * Adds the specified element to this set if it is not already present. * More formally, adds the specified element {@code e} to this set if * this set contains no element {@code e2} such that * {@code Objects.equals(e, e2)}. * If this set already contains the element, the call leaves the set * unchanged and returns {@code false}. * * @param e element to be added to this set * @return {@code true} if this set did not already contain the specified * element */ public boolean add(E e) { return map.put(e, PRESENT)==null; }put(),先执行 hash(key),得到对应的 hash 值,并不直接是 hashCode()/** * Associates the specified value with the specified key in this map. * If the map previously contained a mapping for the key, the old * value is replaced. * * @param key key with which the specified value is to be associated * @param value value to be associated with the specified key * @return the previous value associated with {@code key}, or * {@code null} if there was no mapping for {@code key}. * (A {@code null} return can also indicate that the map * previously associated {@code null} with {@code key}.) */ public V put(K key, V value) { return putVal(hash(key), key, value, false, true); }hash()/** * Computes key.hashCode() and spreads (XORs) higher bits of hash * to lower. Because the table uses power-of-two masking, sets of * hashes that vary only in bits above the current mask will * always collide. (Among known examples are sets of Float keys * holding consecutive whole numbers in small tables.) So we * apply a transform that spreads the impact of higher bits * downward. There is a tradeoff between speed, utility, and * quality of bit-spreading. Because many common sets of hashes * are already reasonably distributed (so don't benefit from * spreading), and because we use trees to handle large sets of * collisions in bins, we just XOR some shifted bits in the * cheapest possible way to reduce systematic lossage, as well as * to incorporate impact of the highest bits that would otherwise * never be used in index calculations because of table bounds. */ static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }*putVal,核心代码!!!/** * Implements Map.put and related methods. * * @param hash hash for key * @param key the key * @param value the value to put * @param onlyIfAbsent if true, don't change existing value * @param evict if false, the table is in creation mode. * @return previous value, or null if none */ final V putVal(int hash, K key, V value, boolean onlyIfAbsent, boolean evict) { Node<K,V>[] tab; Node<K,V> p; int n, i; if ((tab = table) == null || (n = tab.length) == 0) n = (tab = resize()).length; if ((p = tab[i = (n - 1) & hash]) == null) tab[i] = newNode(hash, key, value, null); else { Node<K,V> e; K k; if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k)))) e = p; else if (p instanceof TreeNode) e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value); else { for (int binCount = 0; ; ++binCount) { if ((e = p.next) == null) { p.next = newNode(hash, key, value, null); if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st treeifyBin(tab, hash); break; } if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))) break; p = e; } } if (e != null) { // existing mapping for key V oldValue = e.value; if (!onlyIfAbsent || oldValue == null) e.value = value; afterNodeAccess(e); return oldValue; } } ++modCount; if (++size > threshold) resize(); afterNodeInsertion(evict); return null; }练习package com.bbedu.set_; import java.util.HashSet; import java.util.Iterator; import java.util.Objects; @SuppressWarnings({"all"}) public class HashSetExercise { public static void main(String[] args) { HashSet hashSet = new HashSet(); hashSet.add(new Employee("Jack", 20)); hashSet.add(new Employee("Mary", 18)); hashSet.add(new Employee("Jack", 20)); Iterator iterator = hashSet.iterator(); while (iterator.hasNext()) { Object next = iterator.next(); System.out.println("next=" + next); } } } @SuppressWarnings({"all"}) class Employee { private String name; private int age; public Employee(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; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Employee employee = (Employee) o; return age == employee.age && Objects.equals(name, employee.name); } @Override public int hashCode() { return Objects.hash(name, age); } @Override public String toString() { return "Employee{" + "name='" + name + '\'' + ", age=" + age + '}'; } }package com.bbedu.set_; import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.Objects; public class HashSetExercise02 { public static void main(String[] args) { HashSet hashSet = new HashSet(); hashSet.add(new Employee02("Tim", 20000, new MyDate(1990, 1, 1))); hashSet.add(new Employee02("Rock", 15000, new MyDate(1998, 4, 29))); hashSet.add(new Employee02("Tim", 23333, new MyDate(1990, 1, 1))); Iterator iterator = hashSet.iterator(); while (iterator.hasNext()) { Object next = iterator.next(); System.out.println("next=" + next); } } } class Employee02{ private String name; private double sal; private MyDate birthday; public Employee02(String name, double sal, MyDate birthday) { this.name = name; this.sal = sal; this.birthday = birthday; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getSal() { return sal; } public void setSal(double sal) { this.sal = sal; } public MyDate getBirthday() { return birthday; } public void setBirthday(MyDate birthday) { this.birthday = birthday; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Employee02 that = (Employee02) o; return Objects.equals(name, that.name) && Objects.equals(birthday, that.birthday); } @Override public int hashCode() { return Objects.hash(name, birthday); } @Override public String toString() { return "Employee02{" + "name='" + name + '\'' + ", sal=" + sal + ", birthday=" + birthday + '}'; } } class MyDate { private int year; private int month; private int day; public MyDate(int year, int month, int day) { this.year = year; this.month = month; this.day = day; } public int getYear() { return year; } public void setYear(int year) { this.year = year; } public int getMonth() { return month; } public void setMonth(int month) { this.month = month; } public int getDay() { return day; } public void setDay(int day) { this.day = day; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; MyDate myDate = (MyDate) o; return year == myDate.year && month == myDate.month && day == myDate.day; } @Override public int hashCode() { return Objects.hash(year, month, day); } @Override public String toString() { return "MyDate{" + "year=" + year + ", month=" + month + ", day=" + day + '}'; } }LinkedHashSetLinkedHashSet 是 HashSet 的子类LinkedHashSet 底层是一个 LinkedHashMap,底层维护了一个 数组 + 双向链表LiniedHashSet 根据元素的 hashCode 值来决定元素的存储位置,同时使用链表维护元素的次序,这使得元素看起来是以插入顺序保存的LinkedHashSet 不允许添加重复元素Map 接口Map 与 Collection 并列存在,用于保存具有映射关系的数据:Key-Value (双列元素)Map 中的 key 和 value 可以是任何引用类型的数据,会封装到 HashMap$Node 对象中Map 中的 key不允许重复,当有相同的 key 时,相当于替换Map 中的 value 可以重复key 和 value 都可以为 null,但 key 只能有一个 null,而 value 可以有多个 null常用 String 类来做 key,别的引用类型同样可以key 和 value 存在单向一对一关系(满射关系,即一种映射)常用方法六种遍历方法:package com.bbedu.map_; import java.util.*; public class MapFor { public static void main(String[] args) { HashMap hashMap = new HashMap(); hashMap.put("刘慈欣", "三体"); hashMap.put("张爱玲", "倾城之恋"); hashMap.put("萧红", "呼兰河传"); hashMap.put("托尔斯泰", "复活"); hashMap.put("史铁生", "我与地坛"); // 第一组 Set set = hashMap.keySet(); System.out.println("===增强for==="); for (Object o : set) { System.out.println(o + "-" + hashMap.get(o)); } System.out.println("===迭代器==="); Iterator iterator = set.iterator(); while (iterator.hasNext()) { Object next = iterator.next(); System.out.println(next + "-" + hashMap.get(next)); } // 第二组 Collection values = hashMap.values(); System.out.println("===取value==="); for (Object value : values) { System.out.println(value); } System.out.println("===迭代器==="); Iterator iterator1 = values.iterator(); while (iterator1.hasNext()) { Object next = iterator1.next(); System.out.println(next); } // 第三组 Set set1 = hashMap.entrySet(); System.out.println("===增强for==="); for (Object o : set1) { Map.Entry o1 = (Map.Entry) o; System.out.println(o1.getKey() + "-" + o1.getValue()); } System.out.println("===迭代器==="); Iterator iterator2 = set1.iterator(); while (iterator2.hasNext()) { Object next = iterator2.next(); Map.Entry next1 = (Map.Entry) next; System.out.println(next1.getKey() + "-" + next1.getValue()); } } } 练习package com.bbedu.map_; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; public class MapExercise { public static void main(String[] args) { HashMap<Integer,Employee> map = new HashMap(); Employee tom = new Employee("Tom", 20000, 1); Employee bob = new Employee("Bob", 15000, 2); Employee sam = new Employee("Sam", 19000, 3); map.put(tom.getId(), tom); map.put(bob.getId(), bob); map.put(sam.getId(), sam); System.out.println("===方式1==="); Set set = map.keySet(); Iterator iterator = set.iterator(); while (iterator.hasNext()) { Object next = iterator.next(); Employee employee = (Employee) map.get(next); if(employee.getSal() > 18000){ System.out.println(employee); } } System.out.println("===方式2==="); Set set1 = map.entrySet(); for (Object o : set1) { Map.Entry o1 = (Map.Entry) o; Employee value = (Employee) o1.getValue(); if(value.getSal() > 18000){ System.out.println(value); } } } } class Employee { private String name; private double sal; private int id; public Employee(String name, double sal, int id) { this.name = name; this.sal = sal; this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getSal() { return sal; } public void setSal(double sal) { this.sal = sal; } public int getId() { return id; } public void setId(int id) { this.id = id; } @Override public String toString() { return "Employee{" + "name='" + name + '\'' + ", sal=" + sal + ", id=" + id + '}'; } }HashMap底层机制及源码分析先结论:Hashtable存放的元素是键值对,即 K-VHashtable 的键和值都不能为null,否则会抛出 NullPointerExceptionHashtable 使用的方法基本上和 HashMap一样Hashtable 是线程安全的,HashMap 是线程不安全的扩容机制Hashtable 和 HashMap 对比PropertiesProperties 类继承自 Hashtable 类并且实现了 Map 接口,也是使用一种键值对的形式来保存数据它的特点和 Hashtable 类似Properties 还可以用于 从 xxx.properties 文件中加载数据到Properties 类对象,并进行读取和修改开发中如何选择集合实现类TreeSetTreeMapTreeMap 是 TreeSet 的底层Collections 工具类常用方法package com.bbedu.collections_; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; public class Collections_ { public static void main(String[] args) { // ArrayList 集合,用于测试 ArrayList list = new ArrayList(); list.add("tom"); list.add("jack"); list.add("sam"); list.add("mike"); list.add("smith"); System.out.println(list); System.out.println("===reverse==="); Collections.reverse(list); System.out.println(list); System.out.println("===shuffle==="); for (int i = 0; i < 5; i++) { Collections.shuffle(list); System.out.println(list); } System.out.println("===sort===="); Collections.sort(list); System.out.println(list); System.out.println("===自定义sort==="); Collections.sort(list, new Comparator<>() { @Override public int compare(Object o1, Object o2) { if(o1 instanceof String && o2 instanceof String){ return ((String) o1).length() - ((String) o2).length(); } return 0; } }); System.out.println(list); System.out.println("===swap==="); Collections.swap(list,0, 1); System.out.println(list); System.out.println("===max==="); System.out.println(Collections.max(list)); System.out.println("===自定义max==="); Object max = Collections.max(list, new Comparator() { @Override public int compare(Object o1, Object o2) { return ((String) o1).length() - ((String) o2).length(); } }); System.out.println(max); System.out.println("===frequency==="); System.out.println(Collections.frequency(list, "tom")); System.out.println("===copy==="); ArrayList dest = new ArrayList(); // 需要先给 dest 赋值,大小和 list相同 for (int i = 0; i < list.size(); i++) { dest.add(""); } Collections.copy(dest, list); System.out.println(dest); System.out.println("===replaceAll==="); Collections.replaceAll(list, "tom", "汤姆"); System.out.println(list); } }本章作业package com.bbedu.homework; import java.util.ArrayList; @SuppressWarnings({"all"}) public class Homework01 { public static void main(String[] args) { ArrayList arrayList = new ArrayList(); arrayList.add(new News("广东中山发现8例无症状感染者,均在隔离管控的密接人员中发现")); arrayList.add(new News("经济衰退阴云笼罩 惠誉下调美国2023年GDP增速预期")); for (int i = arrayList.size() - 1; i >= 0; i--) { News news = (News) arrayList.get(i); String s = processTitle(news.getTitle()); System.out.println(s); } } public static String processTitle(String title) { if (title == null) { return ""; } if (title.length() > 15){ return title.substring(0, 15) + "..."; }else{ return title; } } } class News { private String title; private String content; public News(String title) { this.title = title; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } @Override public String toString() { return "News{" + "title='" + title + '\'' + '}'; } }package com.bbedu.homework; import java.util.ArrayList; public class Homework02 { public static void main(String[] args) { Car car1 = new Car("宝马", 300000); Car car2 = new Car("奔驰", 400000); Car car3 = new Car("宾利", 500000); ArrayList<Car> cars = new ArrayList<>(); cars.add(car1); cars.add(car2); cars.add(car3); System.out.println(cars); System.out.println("===增强for==="); for (Car car : cars) { System.out.println(car); } cars.remove(car3); System.out.println(cars); System.out.println(cars.contains(car3)); System.out.println(cars.isEmpty()); cars.clear(); System.out.println(cars); cars.add(car1); cars.add(car2); cars.add(car3); ArrayList<Car> cars1 = new ArrayList<>(); cars1.addAll(cars); System.out.println(cars1); System.out.println(cars1.containsAll(cars)); cars1.removeAll(cars); System.out.println(cars1); } } class Car { private String name; private double price; public Car(String name, double price) { this.name = name; this.price = price; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } @Override public String toString() { return "Car{" + "name='" + name + '\'' + ", price=" + price + '}'; } }package com.bbedu.homework; import java.util.Collection; import java.util.HashMap; import java.util.Set; public class Homework03 { public static void main(String[] args) { HashMap hashMap = new HashMap(); hashMap.put("jack", 650); hashMap.put("tom", 1200); hashMap.put("smith", 2900); printAll(hashMap); System.out.println("===修改jack工资==="); hashMap.replace("jack", 2600); printAll(hashMap); System.out.println("===所有人工资+100==="); Set set = hashMap.keySet(); for (Object o : set) { hashMap.put(o, (Integer) hashMap.get(o) + 100); } printAll(hashMap); } public static void printAll(HashMap hashMap){ Set set = hashMap.keySet(); for (Object o : set) { System.out.println(o + "-" + hashMap.get(o)); } } public static void printAllSal(HashMap hashMap){ Set set = hashMap.keySet(); for (Object o : set) { System.out.println(hashMap.get(o)); } } }package com.bbedu.homework; import java.util.TreeSet; public class Homework05 { public static void main(String[] args) { TreeSet treeSet = new TreeSet(); treeSet.add(new Person()); treeSet.add(new Person()); treeSet.add(new Person()); treeSet.add(new Person()); treeSet.add(new Person()); treeSet.add(new Person()); System.out.println(treeSet); } } class Person implements Comparable{ @Override public int compareTo(Object o) { return 0; } }输出[Person2{id=1002, name='BB'}, Person2{id=1001, name='CC'}] [Person2{id=1002, name='BB'}, Person2{id=1001, name='CC'}, Person2{id=1001, name='CC'}] [Person2{id=1002, name='BB'}, Person2{id=1001, name='CC'}, Person2{id=1001, name='CC'}, Person2{id=1001, name='AA'}]
2023年02月26日
98 阅读
0 评论
0 点赞
1
...
4
5
6
...
11