Java 8 特性
👏被函数式接口@FunctionalInterface(即SAM接口)修饰,表示接口内的抽象方法有且只有一个
此时可使用lambda表达式对带有此注解的接口中抽象方法进行实现
Lambda表达式:用于将函数作为参数,传入方法中,实现函数式编程风格
java
(parameters)->expression 或 (parameters)->{statements;}
例子:
1️⃣排序
java
//传统方法
list.sort(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.length()-o2.length();
}
});
//lambda表达式---省略多余的,看最内部的主要起作用的方法是啥(关注参数和返回值)
list.sort((o1, o2) -> {return o1.length() - o2.length();});
2️⃣将list中名称变成大写
java
//对foreach方法中consumer接口的accept方法(无返回值)
list.forEach((s) -> {System.out.println(s.toUpperCase());});
3️⃣按照条件删除list中部分元素
java
//删除list中以b开头的元素
list.removeIf((lang)->{
if(lang.startsWith("b")){
return true;
}
return false;
});
内置函数式接口
Predicate接口
只有一个参数的返回布尔类型值的断言型接口------应用于判断
java
ArrayList<String> langList = new ArrayList<(Arrays.asList("abc","bv","aaac","a"));
4️⃣查找list中元素字符小于3个字符的元素
java
Predicate<String> predicate1 =(lang)->{
if (lang.length()<=3){
return true;
}
return false;
};
5️⃣查找list中元素以a或者b开头的元素
java
Predicate<String> predicate2 = (lang)->{
if(lang.toLowerCase().startsWith("a")||lang.toLowerCase().startsWith("b")){
return true;
}
return false;
};
6️⃣条件组合:形成"与","或","非"的逻辑关系
java
Predicate<String> predicate3 = predicate1.and(predicate2);
Predicate<String> predicate4 = predicate1.or(predicate2);
Predicate<String> predicate5 = predicate1.negate();
//输出
langList.forEach((lang)->{
if(predicate3.test(lang)){
System.out.println(lang);
}
});
Function接口
接收一个参数并产生结果----对数据作处理
7️⃣list转换成大写字母形式
java
Function<String,String> function1 = (lang)->{
lang = lang.toUpperCase();
return lang;
};
8️⃣list每项加上【】
java
Function<String,String> function2 = (lang)->{
lang = String.format("【%s】",lang);
return lang;
};
9️⃣组合
java
Function<String,String> function3 = function1.andThen(function2);
langList.forEach((lang)->{
String ret = function3.apply(lang);
System.out.println(ret);
});
Comparator接口
比较器接口,比较指定元素值的大小
1️⃣0️⃣比较
java
Comparator<String> comparator1 = (lang1,lang2)->{
int ret = lang1.compareTo(lang2);
if(ret == 0){
/**
* 比较两个字符串,返回它们长度的差值
* 返回值
* 负数:lang1的长度小于lang2的长度
* 正数:lang1的长度大于lang2的长度
*/
return lang1.length()-lang2.length();
}
return ret;
};
1️⃣2️⃣反转
java
Comparator<String> comparator2 = comparator1.reversed();
1️⃣3️⃣排序
java
langList.sort(comparator1);
//输出
langList.forEach((lang)->{
System.out.println(lang);
});
Stream流
应用在一组元素上一次执行的操作系列
1️⃣4️⃣Stream创建
java
ArrayList<String> langList = new ArrayList<>(Arrays.asList("abc","bv","aaac","a","abc","aaac"));
//通过集合对象创建
Stream<String> stream = langList.stream();
//通过Stream.of()方法创建
Stream<String> stream1 = Stream.of("abc", "bv", "aaac", "a", "abc", "aaac");
1️⃣5️⃣过滤集合中的元素(字符数大于5个的元素),并去重
java
stream
//过滤集合中的元素(字符数大于5个的元素)
.filter((lang)->{
if(lang.length() >=3){
return true;
}
return false;
})
//去重
.distinct()
//输出
.forEach((lang)->{
System.out.println(lang);
});
Filter过滤
过滤通过一个predicate接口来过滤并只保留符合条件的元素,该操作属于中间操作,过滤后的结果仍旧可以继续执行其他Stream操作
1️⃣6️⃣过滤Stream中纯小写字母并排序
java
stream
//过滤
.filter((lang)->{
for(int i = 0; i<lang.length();i++){
char c = lang.charAt(i);
if(c >='A'&& c<='Z'){
return true;
}
}
return false;
})
//排序
.sorted((o1,o2)->{
if(o1.length() == o2.length()){
return o1.compareTo(o2);
}
return o1.length()-o2.length();
})
//遍历
.forEach((lang)->{
System.out.println(lang);
});
Sorted排序
中间操作,返回的是排序好后的Stream,不影响原来的数据
Map映射
中间操作,将元素根据指定的function接口来依次将元素转成另外的对象
1️⃣7️⃣转换String字符串为大写,降序后,输出
java
Stream<Integer> stream1 = Stream.of(10, 20, 30, 40, 50, 60);
//映射:对每个元素进行一次处理
stream1.map((n)->{
return n+1;
}).forEach((n)->{
System.out.println(n);
});
List<String> strings = Arrays.asList("abc","bv","aaac","a");
//转换字符串为大写,降序后,输出
strings.stream().map((item)->{
return item.toUpperCase();
}).sorted((s1,s2)->{
return s2.compareTo(s1);
}).forEach((item)->{
System.out.println(item);
});
Match匹配
最终操作,返回一个boolean类型的值
1️⃣8️⃣元素匹配
java
//allMatch:所有元素是否匹配
boolean bool1= strings.stream().allMatch((item)->{
return item.length()==3;
});
System.out.println(bool1);
//anyMatch:任意元素匹配
boolean bool2 =strings.stream().anyMatch((item)->{
return item.length()==3;
}) ;
System.out.println(bool2);
Count计数
最终操作,返回Stream中元素个数,返回值是long
1️⃣9️⃣找到stram中所有以a开头的名称,并统计数量
java
long count = strings.stream().filter((item)->{
return item.startsWith("a");
}).count();
System.out.println(count);
Collect收集
最终操作,返回Stream中元素集合,返回值是集合(List、Set、Map)或者字符串
2️⃣0️⃣将Stream中的元素,收至新集合
- Collectors.toMap()
- Collectors.toList()
- Collectors.toSet()
java
//转换为Map键值对集合:
Map<?,?> map = strings.stream().collect(Collectors.toMap(
(s) -> {return s;},
(sVal) ->{return sVal.length();}
));
System.out.println(map);
2️⃣1️⃣将Stream中的元素,映射后,收集至新集合
java
List<String> numberStrings = Arrays.asList("4344","6641","3432","4543","2222");
//将stream流中的每个元素进行mapping映射操作后,然后收集至一个list集合
List<Integer> numberInt = numberStrings.stream().collect(Collectors.mapping(s->Integer.parseInt(s)*10,Collectors.toList()));
numberInt.forEach(System.out::println);
System.out.println();
2️⃣2️⃣分组操作和分区操作
java
/**
* 分组操作
*/
Stream<String> stream = Stream.of("Basic", "Qbsif", "Html", "CCD", "Hello!");
//按照元素的字符长度,进行分组
Map<Integer, List<String>> resultMap = stream.collect(Collectors.groupingBy(s -> s.length()));
resultMap.forEach((k,v)->{
System.out.println(k+":"+v);
});
System.out.println("-----------------");
Stream<String> stream2 = Stream.of("Basic", "Qbsif", "Html", "CCD", "Hello!");
//按照元素首字母进行分组
Map<Character, List<String>> resultMap2 =stream2.collect(Collectors.groupingBy(s->s.charAt(0)));
resultMap2.forEach((k,v)->{
System.out.println(k+":"+v);
});
System.out.println("-----------------");
/**
* 分区操作
*/
Stream<String> stream3 = Stream.of("Basic", "Qbsif", "Html", "CCD", "Hello!");
Map<Boolean, List<String>> map = stream3.collect(Collectors.partitioningBy(s -> s.length() > 4));
map.forEach((k,v)->{
System.out.println(k+":"+v);
});
👏Map集合补充:
2️⃣3️⃣Map集合的遍历
java
map.forEach((k,v)->{System.out.println(k+":"+v);});
2️⃣4️⃣Map键值对合并
java
HashMap<String,Integer> map = new HashMap<String,Integer>();
map.put("HuaWei MateXT",9999);
map.put("联想小新",6666);
map.put("三星手机",7890);
//Map键值对合并
//key存在,执行合并操作
map.merge("三星手机",10,(olaVal,newVal)->{
return olaVal + newVal;
});
//键不存在,放入map中
map.merge("小米手机",5000,(olaVal,newVal)->{
return olaVal + newVal;
});
Statistics统计
最终操作,返回Stream中元素的各类统计信息,返回值类型是XXXConsumer
stream流必须是IntStream
2️⃣5️⃣统计操作
java
List<Integer> list = Arrays.asList(1,2,3,4,5,6);
//Stream===>IntStream
IntStream intStream = list.stream().mapToInt(s -> s * 10);
//获取统计结果
IntSummaryStatistics statisticsResult = intStream.summaryStatistics();
System.out.println("最大值"+statisticsResult.getMax());
System.out.println("最小值"+statisticsResult.getMin());
System.out.println("平均值"+statisticsResult.getAverage());
System.out.println("累加和"+statisticsResult.getSum());
一个Stream只能操作一次,操作完就关闭了,继续使用这个Stream会报错
Stream不保存数据,不该表数据源
Parallel Streams并行流
Stream中有串行和并行两种,串型Stream上的操作是在一个线程中依次完成,并行Stream操作则是在多个线程上同时进行。
日期时间
2️⃣6️⃣格式化
java
//默认格式:yyyy-MM-dd
LocalTime date = LocalTime.now();
System.out.println(String.format("Date format:%s",date));
//默认格式:HH:mm:ss
LocalTime time = LocalTime.now().withNano(0);
System.out.println(String.format("Time format:%s",time));
//自定义格式:yyyy-MM-dd HH:mm:ss
LocalDateTime dateTime = LocalDateTime.now();
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:ss:dd");
String dateTimeStr = dateTime.format(dateTimeFormatter);
System.out.println(String.format("DateTime format:%s",dateTimeStr));
2️⃣7️⃣字符串转日期格式
java
//字符串格式的日期
String strDatetime = "2024年12月17日";
//将字符串格式的日期转换为LocalDate类型的日期
LocalDate date1 = LocalDate.parse(strDatetime, DateTimeFormatter.ofPattern("yyyy年MM月dd日"));
System.out.println(date1);
2️⃣8️⃣日期的计算
java
//计算一周后的日期
LocalDate localDate = LocalDate.now();
//方法1
LocalDate after1 = localDate.plus(1, ChronoUnit.WEEKS);
System.out.println("一周后日期"+after1);
//方法2
LocalDate after2 = localDate.plusWeeks(1);
System.out.println("一周后日期"+after2);
//计算两个日期间隔多少天,计算间隔多少年,多少月
LocalDate date1 = LocalDate.parse("2021-02-26");
LocalDate date2 = LocalDate.parse("2022-02-26");
Period period = Period.between(date1,date2);
System.out.println("date1到date2相隔"+period.getYears()+"年"+period.getMonths()+"月"+period.getDays()+"日");
//计算两个日期间隔多少天
long day = date2.toEpochDay() - date1.toEpochDay();
System.out.println(date2+"和"+date1+"相差"+day+"天");
2️⃣9️⃣获取指定日期
java
LocalDate today = LocalDate.now();
//获取当前月的第一天
LocalDate firstDayOfMonth = today.with(TemporalAdjusters.firstDayOfMonth());
System.out.println("当前月的第一天"+firstDayOfMonth);
//获取本月最后一天
LocalDate lastDayOfMonth = today.with(TemporalAdjusters.lastDayOfMonth());
System.out.println("当前月的最后一天"+lastDayOfMonth);
//获取下一天
LocalDate nextDay = lastDayOfMonth.plusDays(1);
System.out.println("下一天(次月第一天)"+nextDay);
//获取当年最后一天
LocalDate lastday = today.with(TemporalAdjusters.lastDayOfYear());
System.out.println("当前月第一天:"+lastday);
//获取当年最后一个周日
LocalDate lastSundayOfThisYear = lastday.with(TemporalAdjusters.lastInMonth(DayOfWeek.SUNDAY));
System.out.println("当年最后一个周日"+lastSundayOfThisYear);