java学习笔记385-410,Stream流,反射

前言
b站java课程学习笔记整理。
b站视频: 黑马程序员全套Java教程_Java基础入门视频教程,零基础小白自学Java必备教程
385. 体验Stream流
直接阅读代码的字面意思即可完美展示无关逻辑方式的语义:生成流、过滤姓张、过滤长度为3、逐一打印。
真正的使用了函数式的编程思想。
386. Stream流常见生成方式
Stream流的使用
- 生成流
- 通过数据源(集合,数组等生成流)
list.stream()
- 中间操作
- 一个流后面可以跟随零个或者多个中间操作,其主要目的是打开流,做出某种程度的数据过滤、映射,然后返回一个新的流,交给下一个操作使用
filter()
- 终结操作
- 一个流只能有一个终结操作,当操作执行后,流就被用光了。所以必定是最后一个流执行
forEach()
- 一个流只能有一个终结操作,当操作执行后,流就被用光了。所以必定是最后一个流执行
Stream流的生成方式
Collection
体系的集合可以使用默认方法stream()
生成流default Stream<E> stream()
Map
体系的集合间接的生成流- 数组可以通过
Stream
接口的静态方法of(T...values)
生成流
package StreamDemo;
import java.util.*;
import java.util.stream.Stream;
public class StreamDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
Stream<String> listStream = list.stream();
Set<String> set = new HashSet<>();
Stream<String> setStream = set.stream();
//间接生成流
Map<String,Integer>map = new HashMap<>();
Stream<String> keyStream = map.keySet().stream();
Stream<Integer> valueStream = map.values().stream();
Stream<Map.Entry<String,Integer>>entryStream = map.entrySet().stream();
String[] strArray = {"hello","world"};
Stream<String> strArrayStream = Stream.of(strArray);
Stream<String> stringStream2 = Stream.of("hello","world");
Stream<Integer> intStream = Stream.of(10,20,30);
}
}
387. Steam流之filter
用于对流中的数据进行过滤
Stream<T> filter(Predicate predicate)
: 用于对流中的数据进行过滤。
使用的是Predicate接口中的方法 boolean test(T t)
用法举例:
list.stream.filter(s->s.startsWith("张")).forEach(System.out::println)
可以多个filter”串联”。
388. Steam流中间操作limit&skip
Stream<T> limit(long maxSize)
:返回此流中的元素组成的流,截取前指定参数个数的数据。(取前几个)Stream<T> skip(long n)
:跳过指定参数个数的数据,返回由该流的剩余元素组成的流。(跳过几个)
389. Steam流中间操作concat&distinct
static <T> Stream <T> concat(Stream a,Stream b)
:将两个流合并。
用法:
Stream.concat(s1,s2).forEach(System.out::println);
Stream<T>distinct()
:返回由该流的不同元素(根据object.equals(Object)
)组成的流。(去掉重复的)
390.Steam流中间操作之sorted
Stream<T> sorted()
:返回由此流的元素组成的流,根据自然顺序排序。Stream<T> sorted(Comparator comparator)
:返回由该流的元素组成的流,根据提供的Comparator
进行排序。
比较器举例:
list.stream().sorted((s1,s2)->{
int num = s1.length()-s2.length();
int num2 = num ==0?s1.compareTo(s2):num;
return num2
}).forEach(System.out::println);
391. Steam流中间操作之map&mapToInt
<R> Stream<R> map(Function mapper)
:返回由给定函数应用于此流的元素的结果组成的流。IntStream mapToInt(ToIntFunction mapper)
:返回一个IntStream
其中包括将给定函数应用于此流的元素的结果。IntStream
:表示原始int
流。
392. Steam流终结操作forEach&count
void forEach(Consumer action)
: 对此流的每个元素执行操作。long count()
:返回流元素个数。
393. Stream流综合练习
现在有两个ArrayList集合,分别存储6名男演员名称和6名女演员名称,要求完成如下操作:
- 男演员取名字为3个字的前三个人
- 女演员只要姓林的,不要第一个
- 把过滤后的男演员姓名和女演员姓名合并到一起
- 把上一步操作后的元素作为构造方法的参数创建演员对象,并遍历。
package Stream案例;
import java.util.ArrayList;
import java.util.stream.Stream;
public class StreamTest {
public static void main(String[] args) {
ArrayList<String>manList = new ArrayList<>();
manList.add("周润发");
manList.add("成龙");
manList.add("刘德华");
manList.add("吴京");
manList.add("周星驰");
manList.add("李连杰");
ArrayList<String>womanList = new ArrayList<>();
womanList.add("林心如");
womanList.add("张曼玉");
womanList.add("林青霞");
womanList.add("柳岩");
womanList.add("林志玲");
womanList.add("王祖贤");
Stream<String> manStream = manList.stream().filter(s->s.length()==3).limit(3);
Stream<String> womenStream = womanList.stream().filter(s->s.startsWith("林")).skip(1);
Stream<String> stream = Stream.concat(manStream,womenStream);
//利用map,将此流中的字符串构建成Actor
stream.map(Actor::new).forEach(p->System.out.println(p.getName()));
}
}
394. Stream流的收集操作
Stream流的收集方法
R collect(Collector collector)
- 但是这个收集方法的参数是一个Collector接口
工具类Collectors提供了具体的收集方式
public static <T> Collector toList()
: 把元素收集到List集合中Public static <T> Collector toSet()
: 把元素收集到Set集合中public static Collector toMap(Function keyMapper, Function valueMapper)
: 把元素收集到Map集合中
395. 类加载
当程序要使用某个类时,如果该类还未被加载到内存中,系统就会通过类的加载,类的链接,类的初始化这三个步骤来对类进行初始化。
-
类的加载
-
就是指将class文件写入内存,并位置创建一个
java.lang.Class
对象。 -
任何类被使用时,系统都会为之建立一个
java.lang.Class
对象。
-
-
类的连接
-
验证阶段: 用于检验被加载的类是否有正确的内部结构,并和其他类协调一致。
-
准备阶段: 负责为类的类变量分配内存,并设置默认初始化值。
-
解析阶段: 将类的二进制数据中的符号引用替换为直接引用。
-
-
类的初始化:
- 对类变量进行初始化
类初始化的步骤
- 假如类还没有被加载和连接,则程序被加载并连接该类
- 假如该类的直接父类还未被初始化,则先初始化其直接父类
- 假如类中有初始化语句,则系统依次执行这些初始化语句。
注意: 在执行第二个步骤的时候,系统对直接父类的初始化步骤也遵循初始化步骤1-3.
396.类加载器
Bootstrap class loader
Platform class loader
System class loader
方法:
static ClassLoader getSystemClassLoader()
:返回用于委派的系统类加载器ClassLoader getParent()
: 返回父类加载器进行委派。
Classloader c = ClassLoader.getSystemClassLoader();
System.out.println(c);
Classloader c2 = c.getParent();
System.out.println(c2);
Classloader c3 = c2.getParent();
System.out.println(c3);
397. 反射概述
反射机制: 是指在运行时去获取一个类的变量和方法信息。然后通过获取到的信息来创建对象,调用方法的一种机制。由于这种动态性,可以极大地增强程序的灵活性。程序不用在编译期就完成确定,在运行期仍然可以扩展。
398. 获取class类的对象
我们想要通过反射去使用一个类,首先要获取到该类的字节码文件对象,也就是类型为class类型的对象。
三种方式:
- 使用类的class属性来获取该类对应的class对象。
- 调用对象的
getClass()
方法 - 使用Class类中的静态方法
forName(String className)
三种方式的代码:
package 反射;
public class test {
public static void main(String[] args) throws ClassNotFoundException {
Class<Student> c1 = Student.class;
System.out.println(c1);
Class<Student> c2 = Student.class;
System.out.println(c1 == c2);
System.out.println("---------");
Student s = new Student();
Class<? extends Student> c3 = s.getClass();
System.out.println(c1==c3);
System.out.println("---------");
Class<?> c4 = Class.forName("反射.Student");
System.out.println(c4 == c1);
}
}
399. 反射获取构造方法并使用
Constructor<?> [] getConstructors()
:返回所有公共构造方法对象的数组Constructor<?> [] getDeclaredConstructors()
:返回所有构造方法对象的数组Constructor<?> [] getConstructor(Class<?>...parameterTypes)
:返回单个公共构造方法对象Constructor<?> [] getDeclaredConstructor(Class<?>...parameterTypes)
返回单个构造方法对象
package 反射;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class<?> c = Class.forName("反射.Student");
// 只能拿到公共的构造方法
Constructor<?>[] constructors1 = c.getConstructors();
for(Constructor constructor: constructors1){
System.out.println(constructor);
}
// 所有的构造方法
Constructor<?>[] constructors2 = c.getDeclaredConstructors();
for (Constructor constructor: constructors2){
System.out.println(constructor);
}
// 拿单个的构造方法
Constructor<?> con = c.getConstructor();
Object obj = con.newInstance();
System.out.println(obj);
}
}
400. 反射获取构造方法并使用练习1
通过反射实现:
Student s = new Student("林青霞",30)
;System.out.println(s)
;
package 反射;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class<?> c = Class.forName("反射.Student");
// 只能拿到公共的构造方法
Constructor<?> constructor = c.getConstructor(String.class, int.class);
Object obj = constructor.newInstance("林青霞",30);
System.out.println(obj);
}
}
401. 反射获取构造方法并使用练习2
通过反射实现:
Student s = new Student("林青霞")
;System.out.println(s)
;- 注意,只以名字的构造方法是private的
package 反射;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Class<?> c = Class.forName("反射.Student");
// 只能拿到公共的构造方法
Constructor<?> constructor = c.getDeclaredConstructor(String.class);
// 暴力反射,值为true取消访问检查
constructor.setAccessible(true);
Object obj = constructor.newInstance("林青霞");
System.out.println(obj);
}
}
402. 反射获取成员变量并使用
Field[] getField()
:返回所有公共成员变量对象的数组Field[] getDeclaredField()
:返回所有成员变量对象的数组Field[] getField(String name)
:返回单个公共成员变量对象Field getDeclaredField(String name)
:返回单个成员变量对象
package 反射;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
public class test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
Class<?> c = Class.forName("反射.Student");
// 只能拿到公共的成员变量
Field[] fields = c.getFields();
for(Field field: fields){
System.out.println(field);
}
// 所有的成员变量
Field[] fields2 = c.getDeclaredFields();
for(Field field: fields2){
System.out.println(field);
}
// 只拿单个的
Field nameField = c.getField("name");
Constructor<?> constructor = c.getConstructor();
Object obj = constructor.newInstance();
nameField.set(obj,"好人"); //给对象obj的成员变量nameField赋值为好人。
System.out.println(obj);
}
}
403. 反射获取成员变量并使用练习
跟上集一样
404. 反射获取成员方法并使用
Method[] getMethods()
:返回所有公共成员方法对象的数组,包括继承的Method[] gerDeclaredMethods()
:返回所有成员方法对象的数组,不包括继承的Method getMethod(String name, Class<?>... parameterTypes)
:返回单个公共成员方法对象Method getDeclaredMethod(String name,Class<?> ... parameterTypes)
: 返回单个成员方法对象invoke(obj)
在具有指定参数的指定对象上调用上述得到的method。
405. 反射获取成员方法并使用练习
和前面一样
406. 反射练习:越过泛型检查
package 反射;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
public class test {
public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, NoSuchFieldException {
ArrayList<Integer> array = new ArrayList<>();
array.add(10);
array.add(20);
Class<? extends ArrayList> c = array.getClass();
Method m = c.getMethod("add", Object.class);
m.invoke(array,"hello");
System.out.println(array);
}
}
407. 通过配置文件运行指定方法
package 反射配置练习;
public class Student {
public void study(){
System.out.println("好好学习");
}
}
package 反射配置练习;
public class Teacher {
public void teach(){
System.out.println("教书");
}
}
className=反射配置练习.Student
methodName=study
package 反射配置练习;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
public class test {
public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
Properties prop = new Properties();
FileReader fr = new FileReader("java.txt");
prop.load(fr);
fr.close();
String className = prop.getProperty("className");
String methodName = prop.getProperty("methodName");
Class<?> aClass = Class.forName(className);
Constructor<?> constructor = aClass.getConstructor();
Object obj = constructor.newInstance();
Method m = aClass.getMethod(methodName);
m.invoke(obj);
}
}
408. 模块化
可以加载指定模块(就是模块下新建好一个包,包下新建好一个类的那个模块),而不是整个虚拟机。
409. 模块的基本使用
在模块的src目录下新建一个名为module-info.java的描述性文件,该文件专门定义模块名,访问权限,模块依赖等信息,描述性文件中使用模块导出和模块依赖来进行配置使用。
某个包的导出:
module idea.test {
exports 集合到文件;
}
module imp.test {
requires idea.test;
}
410. 模块服务的使用
步骤
- 在X模块下创建一个包a,在包a下提供一个接口,接口中定义了一个抽象方法
public interface MyService{
void service();
}
- 在包a下创建一个包impl,在该包impl下提供接口的两个实现类b和c
- 在X模块下的描述文件中添加如下配置
- 模块导出:
exports a
- 服务提供:
provides Myservice with b //指定服务的实现类是服务b
- 模块导出:
总结:源码
完结了!作业源码地址是:这里