###开始操作的相关API
一、通过集合来获取Stream对象 ★
Stream stream = list.stream();
二、通过数组来获取Stream对象
Stream stream = Arrays.stream(数组);
三、通过一组指定的值来获取Stream对象
Stream stream = Stream.of(T…ts)
四、生成无限流
Stream stream= Stream.generate(Supplier sup);
/** * 此类用于演示Stream的使用步骤一:创建Stream对象 * 引申: * Stream的使用步骤 * 1、创建Stream对象,指向数据源 * 2、中间操作,处理数据,返回一个新的Stream * 3、终止操作,执行 * 创建Stream对象的方式 * 1、通过集合对象创建Stream * 2、通过数组对象创建Stream * 3、通过一系列值创建Stream * 4、生成无限流 */ public class TestStreamStart { // 1、通过集合对象创建Stream ★ @Test public void test1() { List<Employee> list = EmployeeData.getData();//集合 //获取串行流对象stream Stream<Employee> stream = list.stream(); //获取并行流对象parallelStream // Stream<Employee> parallelStream = list.parallelStream(); //补充:终止操作 stream.forEach(System.out::println); } // 2、通过数组对象创建Stream @Test public void test2() { Stream<String> stream = Arrays.stream(new String[] {"白眉鹰王","青易斧王","紫衫龙王","金毛狮王"}); stream.forEach(System.out::println); } // 3、通过一系列值创建Stream @Test public void test3() { Stream<String> of = Stream.of("周芷若","小昭","殷离","赵敏"); of.forEach(System.out::println); } // 4、生成无限流 @Test public void test4() { Stream<Double> stream = Stream.generate(Math::random); stream.forEach(System.out::println); } //案例:演示链式调用(流式编程) @Test public void exec1() { //测试1 // EmployeeData.getData().stream().forEach(System.out::println); //测试2 Person p = new Person(); // p.eat(); // p.sleep(); // p.play(); // p.study(); p.eat().sleep().play().study(); } } class Person{ public Person eat() { System.out.println("吃"); return this; } public Person sleep() { System.out.println("睡"); return this; } public Person play() { System.out.println("玩"); return this; } public Person study() { System.out.println("学"); return this; } }
###中间操作的相关API
* filter(Predicate):根据条件过滤
* limit(long max):截取size<=max的元素
* skip(long s):跳过前s个
* distinct():返回去重后的元素集合,根据hashCode和equals方法判断重复项
* map(Function):映射成新元素
* flatMap(Function):映射成Stream类型的新元素
* sorted():自然排序
* sorted(Comparator):定制排序
*
/** * 此类用于演示Stream的使用步骤二:中间操作 * 特点: * ①每个中间操作方法,都会返回一个持有结果的新的Stream对象 * ②中间操作是“惰性求值”,必须等待终止操作后,才会有处理结果 * ③Stream是一次性消费,每次消费后,则不能再次消费,除非重新创建新的Stream * ④中间操作可以实现链式调用! * 常见方法: * filter(Predicate):过滤 * skip(n):去掉前几项 * limit(n):获取前n项 * distinct():去重 * map(Function):映射 * flatMap(Function):映射,返回Stream * sorted():自然排序,要求元素本身实现Comparable接口 * sorted(Comparator):定制排序 */ public class TestStreamMiddle { List<Employee> list; @Before public void before() { list = EmployeeData.getData(); } /* * 筛选与切片 * filter(Predicate p)——接收 Lambda , 从流中排除某些元素。 limit(n)——截断流,使其元素不超过给定数量。 skip(n) —— 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补 distinct()——筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素 */ @Test public void test1() { //1.创建Stream对象 Stream<Employee> stream = list.stream(); //2.中间操作 //方式一:filter过滤 // Stream<Employee> filter = stream.filter(t->t.getGender()=='男'); //方式二:limit限制,返回不超过指定条目数的数据 // Stream<Employee> limit = stream.limit(5); //方法三:skip(n),跳过指定的n条数据 // Stream<Employee> skip = stream.skip(3); //方法四:distinct()去重:两个元素通过equals判断,如果返回true,则为重复项,一般往往需要重写元素的equals和hashCode方法 Stream<Employee> distinct = stream.distinct(); //3.终止操作 distinct.forEach(System.out::println); } /** * 映射 * map:映射(将元素映射成任意类型) * flatMap:映射(将元素映射成Stream类型) */ @Test public void test2() { //1.创建Stream对象 Stream<Employee> stream = list.stream(); //2.中间操作 //方法5:map // Stream<String> map = stream.map(Employee::getName); // Stream<String> filter = map.filter(s->s.contains("段")); Stream<Stream<Object>> map = stream.map(TestStreamMiddle::fromEmployeeToStream); //方法6:flatMap // Stream<Object> flatMap = stream.flatMap(TestStreamMiddle::fromEmployeeToStream); //3.终止操作 // filter.forEach(System.out::println); map.forEach(System.out::println); } /* * 排序 * sorted()——自然排序 sorted(Comparator com)——定制排序 */ @Test public void test3() { //1.开始操作 Stream<Employee> stream = list.stream(); //2.中间操作 //方法7:sorted自然排序 // Stream<Employee> sorted = stream.sorted(); //方法8:sorted(Comparator) 定制排序 Stream<Employee> sorted = stream.sorted((o1,o2)->Double.compare(o2.getSalary(), o1.getSalary())); //3.终止操作 sorted.forEach(System.out::println); } //将Employee转换成Stream public static Stream<Object> fromEmployeeToStream(Employee e){ return Stream.of(e.getName(),e.getAge(),e.getGender(),e.getSalary()); } //案例:获取工资>6000的,第2条——第8条数据,并且去掉重复项,最后打印 @Test public void exec1() { EmployeeData. getData(). stream(). filter(t->t.getSalary()>6000). skip(1). limit(7). distinct(). forEach(System.out::println); } //练习1:获取员工姓名长度大于2的员工的姓名。 @Test public void exec2() { list.stream().map(Employee::getName).filter(s->s.length()>2).forEach(System.out::println); } //练习2:获取员工工资>5000并且年龄<30的员工的工资 @Test public void exec3() { list.stream().filter(e->e.getAge()<30&&e.getSalary()>5000).map(Employee::getSalary).forEach(System.out::println); } //练习3:最老的三个员工的工资 @Test public void exec4() { list.stream().sorted((e1,e2)->Integer.compare(e2.getAge(),e1.getAge())).limit(3).map(Employee::getSalary).forEach(System.out::println); } }
###终止操作的相关API
* allMatch:测试是否全部匹配
* anyMatch:测试是否至少有一个匹配
* noneMatch:测试是否所有的都不匹配
* findFirst:返回第一个
* findAny:返回并行流中的任意一个
* count:统计个数
* max(comparator):返回最大值
* min(comparator):返回最小值
* forEach(Consumer):内部迭代(遍历)
* reduce(BinaryOperator):归约,往往和map搭配使用
/** * 此类用于演示Stream的使用步骤三:终止操作 * 常见方法: * reduce:归约 ★ * forEach:内部迭代 ★ * max:求最大值 * min:求最小值 * count:统计个数 ★ * allMatch:检测是否所有元素都匹配指定条件 * anyMatch:检测是否至少有一个元素匹配指定条件 * noneMatch:检测是否所有元素都不匹配指定条件 * findFirst:返回第一个元素 * findAny:返回任意一个元素 * collect:将Stream转换成集合对象 */ public class TestStreamEnd { List<Employee> list; @Before public void before() { list = EmployeeData.getData(); } /** * 匹配与查找 * allMatch(Predicate p)——检查是否匹配所有元素 anyMatch(Predicate p)——检查是否至少匹配一个元素 noneMatch(Predicate p)——检查是否没有匹配的元素 findFirst——返回第一个元素 findAny——返回当前流中的任意元素 */ @Test public void test1() { //1.开始操作:创建Stream对象 Stream<Employee> stream = list.stream(); //2.中间操作(支持0——n步) //3.终止操作 boolean allMatch = stream.anyMatch(e->e.getSalary()>10000); System.out.println(allMatch); } /* * 统计和迭代 * count * max * min * forEach */ @Test public void test2() { //1.开始操作:创建Stream对象 Stream<Employee> stream = list.stream(); //2.中间操作(支持0——n步) //3.终止操作 //方法1:count统计 // long count = stream.count(); // System.out.println(count); //方法2:max求最大值 Optional<Employee> max = stream.max((o1,o2)->o1.getAge()-o2.getAge()); System.out.println(max); } /* * 归约 * reduce:反复结合流中的元素 */ @Test public void test3() { //1.开始操作:创建Stream对象 Stream<Employee> stream = list.stream(); //2.中间操作(支持0——n步) //3.终止操作 Optional<Double> sum = stream.map(Employee::getSalary).reduce((t,u)->t+u); System.out.println(sum); } /* *收集 * collect:收集 */ @Test public void test4() { //1.开始操作:创建Stream对象 Stream<Employee> stream = list.stream(); //2.中间操作(支持0——n步) //3.终止操作 List<Employee> collect = stream.collect(Collectors.toList()); System.out.println(collect); } //练习2:员工姓名中包含“马”的员工个数 @Test public void exec2() { Optional<Integer> reduce = list.stream().filter(t->t.getName().contains("马")).map(t->1).reduce((t,u)->t+u); System.out.println(reduce); } //练习:返回最高的工资: @Test public void exec1() { Optional<Double> max = list.stream().map(Employee::getSalary).max(Double::compare); System.out.println(max); } }
JDK8对接口的改进
JDK8:
说明:接口中允许出现静态方法和默认方法
语法:
静态方法: public static 返回类型 方法名(参数列表){ } 默认方法: public default 返回类型 方法名(参数列表){ }
使用特点:
1、静态方法不能被实现类或子接口继承,只能通过所在的接口名调用!
2、默认方法具备继承性。可以被实现类或子接口继承过去
解决同名冲突的问题:
1、类优先原则
当父类或实现的接口中出现了同名并且已经实现好的方法时,如果子类中没有重写,则默认使用的是父类的方法
2、当实现的多个接口中出现了同名并且已经实现好的方法时,子类必须重写该方法,否则报错!
JDK9:
说明:接口中允许私有方法
语法:
private 返回类型 方法名(参数列表){ //代码 }
Optional的特性
理解:
Optional实质上是一个容器,里面包装了具体类型的对象。可以避免对象出现空指针异常的现象
方法:
of ofNullable orElse
重复注解
说明:jdk8支持重复注解
语法:
在被修饰的数据上方:
@注解类名
@注解类名
…
示例:
public class TestJava8Ann { @MyAnn @MyAnn // @AnnArray({@MyAnn,@MyAnn}) String name; } @Repeatable(AnnArray.class) @interface MyAnn{ //语法:类型 value() [default 值]; } @interface AnnArray{ MyAnn[] value(); }
##日期API
第一代日期:
Date类
SimpleDateFormat类
Date date = new Date();//当前时间 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh::mm::ss"); String dateString = sdf.format(date);
/** * 此类用于演示第一代日期类 * Date * new Date(); * getTime() * SimpleDateFormat * format * parse */ public class TestDate1 { //创建Date对象,表示一个时间,精确到毫秒 @Test public void test1() { //代表当前系统时间 Date d1 = new Date(); System.out.println(d1); //获取距离1970-1-1的毫秒数 System.out.println(d1.getTime()); } //测试SimpleDateFormat,格式化或解析日期 @Test public void test2() throws ParseException { Date d=new Date(); //1.创建SimpleDateFormat对象 //①使用默认的格式 18-8-8 下午4:25 // SimpleDateFormat sdf = new SimpleDateFormat(); //②使用指定的格式【建议】 SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 hh小时mm分钟ss秒 S毫秒"); //-------------格式化日期(将日期转换成字符串)------------ String format = sdf.format(d); System.out.println(format); //------------解析字符串为日期(将字符串转换成日期)-------- String s = "2018年12月12日 12小时12分钟12秒 12毫秒"; Date date = sdf.parse(s); System.out.println(date); } }
第二代日期:
Calendar抽象类:更侧重于获取和设置日历字段
Calendar date = Calendar.getInstance(); System.out.println(date); int year = date.get(Calendar.YEAR); int month = date.get(Calendar.MONTH); int day = date.get(Calendar.DAY_OF_MONTH); System.out.println(year+"年"+(month+1)+"月"+day+"日");
/** * 此类用于演示第二代日期类 * Calendar */ public class TestDate2 { @Test public void test1() { //1.获取一个Calendar对象 Calendar c = Calendar.getInstance(); // System.out.println(c); //2.获取日历字段 System.out.println("年:"+c.get(Calendar.YEAR)); System.out.println("月:"+(c.get(Calendar.MONTH)+1)); System.out.println("日:"+c.get(Calendar.DAY_OF_MONTH)); System.out.println("小时:"+c.get(Calendar.HOUR)); System.out.println("分钟:"+c.get(Calendar.MINUTE)); System.out.println("秒:"+c.get(Calendar.SECOND)); System.out.println("------------------------------------------"); //3.设置具体的时间 c.set(2000, 1, 1); System.out.println("年:"+c.get(Calendar.YEAR)); System.out.println("月:"+(c.get(Calendar.MONTH)+1)); System.out.println("日:"+c.get(Calendar.DAY_OF_MONTH)); System.out.println("小时:"+c.get(Calendar.HOUR)); System.out.println("分钟:"+c.get(Calendar.MINUTE)); System.out.println("秒:"+c.get(Calendar.SECOND)); } }
第三代日期:
//1.LocalDate/LocalTime/LocalDateTime————>Calendar @Test public void test1() { //①创建日期对象 LocalDateTime ldt = LocalDateTime.now(); //System.out.println(ldt); //②获取日历字段 int year = ldt.getYear(); int month = ldt.getMonthValue(); int day = ldt.getDayOfMonth(); int hour = ldt.getHour(); int minute = ldt.getMinute(); int second = ldt.getSecond(); System.out.println(year+"年"+month+"月"+day+"日 "+hour+"小时"+minute+"分钟"+second+"秒"); } //2.Instant————————>Date @Test public void test2() { //①创建Instant对象 Instant now = Instant.now(); //②实现Instant和Date之间的转换 //Instant——————>Date Date date = Date.from(now); System.out.println(date); //Date——————>Instant Instant instant = date.toInstant(); System.out.println(instant); } //3.DateTimeFormatter——————>SimpleDateFormat /* * 可以格式化LocalDateTime,也可以格式化Instant */ @Test public void test3() { LocalDateTime ldt = LocalDateTime.now(); //①创建DateTimeFormatter对象 DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd kk::mm::ss"); //②格式化日期(日期——————>字符串) String format = dtf.format(ldt); System.out.println(format); //③解析日期(字符串——>日期) LocalDateTime parse = LocalDateTime.parse("2018-08-08 16::32::21", dtf); System.out.println(parse); }