一、java8与函数式编程
1.Lambda表达式
Lambda表达式允许开发人员编写简洁的“计算片段”,并将他们传递给其他代码。接受代码可以选择再核实的时候来执行“计算片段”
Lambda表达式的格式:参数、箭头->、以及表达式
①如果负责计算的代码无法用一个表达式标识,可以用{}包括代码并明确使用return语句,例:
String[] strings = {"aa","aaaa","a","aaaa"}
/** 旧写法 **/
class LengthComparator implements Comparator<String> {
@Overrite
public int compare(String first,String second) {
return Integer.compare(first.length(),second.length());
}
}
Arrays.sort(strings,new LengthComparator());
/** 新写法 **/
Comparator<String> lengthComparator = (String first, String second) -> {
//return Integer.compare(first.length(),second.length());
if(first.length() < second.length()) return -1;
else if(first.length() > second.length()) return 1;
else return 0;
}
Arrays.sort(strings,lengthComparator);
②如果表达式没有参数,可以使用小括号代替,例:
Thread t = new Thread( () -> {
for(i=1;i<10;i++) {
System.out.println(i);
}
})
③如果一个lambda表达式的参数类型是可以被推导的,那么可以省略他们的类型,例:
Comparator<String> lengthComparator = (first, second) -> return Integer.compare(first.length(),second.length());
对于只包含一个抽象方法的接口,你可以通过lambda表达式来创建该接口的对象,这种接口被称为函数式接口。即函数式接口只能包含一个抽象方法,因为java8中接口可以声明非抽象的方法。
方法引用
三种方式:
对象::实例方法
类::静态方法
类::实例方法
@Test
public void demo1() {
//方法引用
Thread myThread = new Thread(System.out::println);
myThread.run();
class Greeter{
public void greet() {
System.out.println("方法引用");
}
}
class ConcurrentGeeter extends Greeter {
public void greet() {
Thread greetThread = new Thread(super::greet);
greetThread.start();
}
}
Greeter greeter = new ConcurrentGeeter();
greeter.greet();
}
构造器引用
与方法引用类似,不同的是在构造器引用中方法名是new。
public void demo2() {
List<String> labels = new ArrayList<>();
Stream<Button> stream = labels.stream().map(Button::new);
List<Button> buttons = stream.collect(Collectors.toList());
}
变量作用域
lambda表达式的方法体与嵌套代码块有着相同的作用域,因此也适用同样的命名冲突和屏蔽规则。在lambda表达式中不允许声明一个与局部变量同名的参数或者局部变量。
默认方法
静态方法
2.Stream api
一个stream表面上看与一个集合很类似,允许你改变和获取数据,但实际上它与集合有很大的区别:
stream自己不会存储元素;
stream操作不会改变源对象;
stream操作符可能是延时执行的,意味着他们会等到需要结果的时候才执行。
stream转换 filter,map,flatMap
filter方法
filter:产生一个新的流,其中包含符合某个特定条件的所有元素
public void demo3() {
List<String> wordList = Arrays.asList(new String[]{"a","b","c","cc"});
Stream<String> words = wordList.stream();
//流只能使用一次,此处打印的话下面就不能使用了
System.out.println(words.count());
Stream<String> longWords = words.filter(w->w.length()>1);
System.out.println(longWords.count());
}
map方法
map:对一个流中的值进行某种形势的转换,将源stream中的元素传递给一个执行转换的函数Function<? super T,? extends T>,返回转换后的stream
public void demo4() {
List<String> wordList = Arrays.asList(new String[]{"a","b","c","cc"});
Stream<String> words = wordList.stream();
//流只能使用一次,此处打印的话下面就不能使用了
//System.out.println(words.count());
Stream<String> longWords = words.map(String::toUpperCase);
System.out.println(longWords.collect(Collectors.toList()).toString());
}
flatMap方法
flatMap:monads理论实现,将多个函数结果展开。个人理解就是递归调用或者链式调用,获取最小单位
public void demo6() {
List<String> wordList = Arrays.asList(new String[]{"aaa","bbb","cccc","ddd"});
//Stream<Stream<Character>> result = wordList.stream().map(LambdaTest::characterStream);
//System.out.println(result.collect(Collectors.toList()));
Stream<Character> result = wordList.stream().flatMap(LambdaTest::characterStream);
System.out.println(result.collect(Collectors.toList()));
}
public static Stream<Character> characterStream(String s) {
List<Character> result = new ArrayList<>();
for (char c : s.toCharArray()) {
result.add(c);
}
return result.stream();
}
limit方法
limit(n):返回一个包含n个元素的新流。这个方法适用于裁剪制定长度的流。
public void demo7() {
//产生100个随机数字
Stream<Double> randoms = Stream.generate(Math::random).limit(100);
System.out.println(randoms.collect(Collectors.toList()));
List<String> wordList = Arrays.asList(new String[]{"aaa","bbb","cccc","ddd"});
Stream<String> wordLimit = wordList.stream().limit(2);
System.out.println(wordLimit.collect(Collectors.toList()));
}
skip方法
skip(n):丢弃掉前面n个元素。
public void demo8() {
List<String> wordList = Arrays.asList(new String[]{"aaa","bbb","cccc","ddd"});
Stream<String> wordLimit = wordList.stream().skip(2);
System.out.println(wordLimit.collect(Collectors.toList()));
}
concat方法
concat(Stream a,Stream b):将两个流连接合并为一个流
public void demo9() {
List<String> wordList1 = Arrays.asList(new String[]{"aaa","bbb","cccc","ddd"});
List<String> wordList2 = Arrays.asList(new String[]{"1","2","3","4"});
Stream<String> concat = Stream.concat(wordList1.stream(), wordList2.stream());
System.out.println(concat.collect(Collectors.toList()));
//打印结果:[aaa, bbb, cccc, ddd, 1, 2, 3, 4]
}
distinct方法
distinct():根据原始流中的元素,返回一个具有相同顺序并剔除了重复元素的新流。
public void demo10() {
List<String> wordList = Arrays.asList(new String[]{"aaa","bbb","aaa","bbb","ccc","ddd","bbb","aaa",});
Stream<String> distinct = wordList.stream().distinct();
System.out.println(distinct.collect(Collectors.toList()));
//打印结果:[aaa, bbb, ccc, ddd]
}
sort方法
sorted():实现了Comparable接口
public void demo11() {
List<Integer> wordList = Arrays.asList(new Integer[]{1,4,2,2,6,3,7,4});
Stream<Integer> sorted = wordList.stream().sorted();
System.out.println(sorted.collect(Collectors.toList()));
//打印结果:[1, 2, 2, 3, 4, 4, 6, 7]
}
sorted(比较器):参数为一个Comparator对象
public void demo12() {
List<String> wordList = Arrays.asList(new String[]{"aa","bbb","a","bb","cc","dd","b","aaa",});
Stream<String> sorted = wordList.stream().sorted((first,second) -> Integer.compare(first.length(), second.length()));
System.out.println(sorted.collect(Collectors.toList()));
//打印结果:[a, b, aa, bb, cc, dd, bbb, aaa]
}
max
返回Stream中的最大值。
返回对象为:Optional
min
返回stream中的最小值
返回对象为:Optional
fildFirst
返回非空集合中的第一个值,通常与filter方法结合使用。
findAny
找到任意的一个匹配的元素,这个方法在对stream进行并行执行时十分有效,因为只要再任何片段中发现了第一个匹配元素,就会结束整个计算。
anyMatch
流中是否含有匹配元素
allMatch
所有元素都匹配
noneMatch
没有元素匹配
reduce
如果你希望对元素求和,或者以其他方式将流中的元素组合为一个值,你可以使用reduce方法。
public void demo13() {
List<Integer> wordList = Arrays.asList(new Integer[]{1,4,2,2,6,3,7,4});
Optional<Integer> reduce = wordList.stream().reduce((x,y) -> x + y);
System.out.println(reduce.get());
//打印结果:29
}
public void demo13() {
List<String> wordList = Arrays.asList(new String[]{"aa","bbb","a","bb","cc","dd","b","aaa",});
Optional<String> reduce = wordList.stream().reduce((x,y) -> x + y);
System.out.println(reduce.get());
//打印结果:aabbbabbccddbaaa
}
collect
前面已经有应用
Collectors.joining()的用法:
将流中所有字符串连接收集起来
public void demo14() {
List<String> wordList = Arrays.asList(new String[]{"aa","bbb","a","bb","cc","dd","b","aaa",});
String collect = wordList.stream().collect(Collectors.joining());
System.out.println(collect);
//打印结果:aabbbabbccddbaaa
}
Collectors.joining(分隔符)的用法:
将流中所有字符串连接收集起来并再中间添加分隔符
public void demo15() {
List<String> wordList = Arrays.asList(new String[]{"aa","bbb","a","bb","cc","dd","b","aaa",});
String collect = wordList.stream().collect(Collectors.joining("|"));
System.out.println(collect);
//打印结果:aa|bbb|a|bb|cc|dd|b|aaa
}
Collectors.summarizing
将Stream结果聚合为一个总和,平均值、最大值、最小值。
public void demo16() {
List<String> wordList = Arrays.asList(new String[]{"aa","bbb","a","bb","cc","dd","b","aaa",});
IntSummaryStatistics collect = wordList.stream().collect(Collectors.summarizingInt(String::length));
System.out.println("元素长度平均值:" + collect.getAverage());
System.out.println("数量:" + collect.getCount());
System.out.println("长度最大是:" + collect.getMax());
System.out.println("长度最小是:" + collect.getMin());
System.out.println("所有元素长度求和:" + collect.getSum());
/**打印结果:
元素长度平均值:2.0
数量:8
长度最大是:3
长度最小是:1
所有元素长度求和:16
**/
}
3.javaFX
4.新的日期事件API
Instant
表示时间轴上的一个点
Duration
表示两个瞬时点之间的时间量
public void demo1() throws Exception {
// 计算两个瞬时点之间的时间距离
Instant now1 = Instant.now();
System.out.println(now1);//打印:2022-06-10T10:08:05.622685500Z
//?疑似带时区,执行时间为下午18:08:05.622685500Z
TimeUnit.SECONDS.sleep(5);
Instant now2 = Instant.now();
Duration between = Duration.between(now1, now2);
System.out.println(between.toMillis());//打印:5030
}
LocalDate
LocalDate是一个带有年份/月份/当月天数的日期。可以使用now或者of创建。
public void demo2() {
LocalDate now = LocalDate.now();
System.out.println(now);//2022-06-10
LocalDate birthday = LocalDate.of(1992, 5, 21);
System.out.println(birthday);//1992-05-21
LocalDate birthday2 = LocalDate.of(92, 5, 21);
System.out.println(birthday2);//0092-05-21
int dayOfMonth = now.getDayOfMonth();
System.out.println(dayOfMonth);//10
int dayOfYear = now.getDayOfYear();
System.out.println(dayOfYear);//161
DayOfWeek dayOfWeek = now.getDayOfWeek();
System.out.println(dayOfWeek);//FRIDAY
Month month = now.getMonth();
System.out.println(month);//JUNE
int monthValue = now.getMonthValue();
System.out.println(monthValue);//6
}
5.并发增强
6.Nashorn
内置的高质量的JavaScript引擎,可以在JVM上执行JavaScript,并且与Java代码进行交互操作。