参考链接:
https://blog.csdn.net/haiyoung/article/details/52693212
一、接口的默认方法
使用default方法我们可以添加一个方法的实现到接口中。
public interface Formula {
double calculate(int a);
default double sqrt(int a) {
return Math.sqrt(a);
}
}
public class FormulaImpl implements Formula {
public static void main(String[] args) {
FormulaImpl formulaImpl = new FormulaImpl();
double result1 = formulaImpl.calculate(100);
double result2 = formulaImpl.sqrt(16);
System.out.println("result1: " + result1); // 100.0
System.out.println("result2: " + result2); // 4.0
}
@Override
public double calculate(int a) {
return sqrt(a * 100);
}
}
二、Lambda表达式
使用Lambda表达式对List集合进行排序
List<String> names = Arrays.asList("peter", "anna", "mike", "xenia");
// traditional way
Collections.sort(names, new Comparator<String>(){
@Override
public int compare(String a, String b) {
// return b.compareTo(a);
return a.compareTo(b);
}
});
System.out.println("traditional way names: " + names.toString());
// Java 8 lambda way
Collections.sort(names, (String a, String b) -> {
return a.compareTo(b);
});
System.out.println("Java 8 lambda way names: " + names.toString());
// Java 8 lambda way 2
Collections.sort(names, (String a, String b) -> a.compareTo(b));
System.out.println("Java 8 lambda way 2 names: " + names.toString());
// Java 8 lambada way 3, only one line code, remove {} and return, even parameter type
Collections.sort(names, (a, b) -> a.compareTo(b));
System.out.println("Java 8 lambda way 3 names: " + names.toString());
运行结果:
traditional way names: [anna, mike, peter, xenia]
Java 8 lambda way names: [anna, mike, peter, xenia]
Java 8 lambda way 2 names: [anna, mike, peter, xenia]
Java 8 lambda way 3 names: [anna, mike, peter, xenia]
三、函数式接口
@FunctionalInterface
interface Converter<F, T> {
T convert(F from);
}
// Converter<String, Integer> converter = (from) -> Integer.valueOf(from);
Converter<String, Integer> converter = Integer::valueOf;
Integer converted = converter.convert("123");
Converter<String, Double> converter2 = (from) -> Double.valueOf(from);
Double converted2 = converter2.convert("123.54");
四、方法与构造函数引用
public class Person {
String firstName;
String lastName;
Person(){}
Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
Person(String firstName) {
this.firstName = firstName;
this.lastName = "Liang";
}
@Override
public String toString() {
return "Person [firstName=" + firstName + ", lastName=" + lastName + "]";
}
interface PersonFactory<P extends Person> {
P create(String firstName, String lastName);
}
public static void main(String[] args) {
PersonFactory<Person> personFactory = Person::new;
Person person = personFactory.create("Perter", "Parker");
System.out.println("person: " + person.toString());
}
}
五、Lambda 作用域
在lambda表达式中访问外层作用域和老版本的匿名对象中的方式很相似。你可以直接访问标记了final的外层局部变量,或者实例的字段以及静态变量。
六、访问局部变量
// final int num = 1;
int num = 1; // don't allow to modify this variable
Converter<Integer, String> converter3 = (from) -> String.valueOf(from + num);
String converted3 = converter3.convert(2);
System.out.println("converted: " + converted); // 123
System.out.println("converted2: " + converted2); // 123.54
System.out.println("converted3: " + converted3); // 3
七、访问对象字段与静态变量
public class Lambda4 {
static int outerStaticNum;
int outerNum;
interface Converter<F, T> {
T convert(F from);
}
void testScopes() {
Converter<Integer, String> stringConverter1 = (from) -> {
outerNum = 23;
return String.valueOf(from);
};
Converter<Integer, String> stringConverter2 = (from) -> {
outerNum = 72;
return String.valueOf(from);
};
}
}
八、访问接口的默认方法
Predicate 接口
Predicate 接口只有一个参数,返回boolean类型。该接口包含多种默认方法来将Predicate组合成其他复杂的逻辑(比如:与,或,非):
// Predicate interface
Predicate<String> predicate = (s) -> s.length() > 0;
System.out.println(predicate.test("foo")); // true
System.out.println(predicate.negate().test("foo")); // false
Predicate<Boolean> nonNull = Objects::nonNull;
Predicate<Boolean> isNull = Objects::isNull;
Predicate<String> isEmpty = String::isEmpty;
Predicate<String> isNotEmpty = isEmpty.negate();
Function 接口
// Function interface
Function<String, Integer> toInteger = Integer::valueOf;
Function<String, String> backToString = toInteger.andThen(String::valueOf);
System.out.println(backToString.apply("123")); // 123
Supplier 接口
// Supplier interface
Supplier<Person> personSupplier = Person::new;
personSupplier.get();
Consumer 接口
// Consumer interface
Consumer<Person> greeter = (p) ->
System.out.println("Hello, " + p.firstName); // Hello, Luke
greeter.accept(new Person("Luke", "Sky"));
Comparator 接口
// Comparator interface
Comparator<Person> comparator = (p1, p2) ->
p1.firstName.compareTo(p2.firstName);
Person p1 = new Person("John", "Doe");
Person p2 = new Person("Alice", "Wonderland");
System.out.println(comparator.compare(p1, p2)); // 9
System.out.println(comparator.reversed().compare(p1, p2)); // -9
Optional 接口
Optional 不是函数是接口,这是个用来防止NullPointerException异常的辅助类型,这是下一届中将要用到的重要概念,现在先简单的看看这个接口能干什么:
Optional 被定义为一个简单的容器,其值可能是null或者不是null。在Java 8之前一般某个函数应该返回非空对象但是偶尔却可能返回了null,而在Java 8中,不推荐你返回null而是返回Optional。
// Optional interface
Optional<String> optional = Optional.of("bam");
System.out.println(optional.isPresent()); // true
System.out.println(optional.get()); // bam
System.out.println(optional.orElse("fallback")); // bam
optional.ifPresent((s) -> System.out.println(s.charAt(0))); // b
Stream 接口
java.util.Stream 表示能应用在一组元素上一次执行的操作序列。Stream 操作分为中间操作或者最终操作两种,最终操作返回一特定类型的计算结果,而中间操作返回Stream本身,这样你就可以将多个操作依次串起来。Stream 的创建需要指定一个数据源,比如 java.util.Collection的子类,List或者Set, Map不支持。Stream的操作可以串行执行或者并行执行。
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class StreamDemo {
public static void main(String[] args) {
List<String> stringCollection = new ArrayList<>();
stringCollection.add("ddd2");
stringCollection.add("aaa2");
stringCollection.add("bbb1");
stringCollection.add("aaa1");
stringCollection.add("bbb3");
stringCollection.add("ccc");
stringCollection.add("bbb2");
stringCollection.add("ddd1");
// Filter
stringCollection.stream()
.filter((s) -> s.startsWith("a"))
.forEach(System.out::println); // forEach is final operation
// Sort
stringCollection.stream()
.sorted()
.filter((s) -> s.startsWith("a"))
.forEach(System.out::println);
System.out.println("stringCollection: " + stringCollection.toString());
// Map
stringCollection.stream()
.map(String::toUpperCase)
.sorted((a, b) -> b.compareTo(a))
.forEach(System.out::println);
// Match
boolean anyStartsWithA =
stringCollection.stream()
.anyMatch((s) -> s.startsWith("a"));
System.out.println(anyStartsWithA);
boolean allStartsWithA =
stringCollection.stream()
.allMatch((s) -> s.startsWith("a"));
System.out.println(allStartsWithA);
boolean noneStartsWithZ =
stringCollection.stream()
.noneMatch((s) -> s.startsWith("z"));
System.out.println(noneStartsWithZ);
// Count final operation
long startWithB =
stringCollection.stream()
.filter((s) -> s.startsWith("b"))
.count();
System.out.println(startWithB);
// Reduce final operation
Optional<String> reduced =
stringCollection.stream()
.sorted()
.reduce((s1, s2) -> s1 + "~" + s2);
reduced.ifPresent(System.out::println);
}
}
并行Streams
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
public class ParallelStream {
public static void main(String[] args) {
int max = 1000000;
List<String> values = new ArrayList<>(max);
for (int i=0; i<max; i++) {
UUID uuid = UUID.randomUUID();
values.add(uuid.toString());
}
// serial and parrel sort
long t0 = System.nanoTime();
// long count = values.stream().sorted().count(); // serial
long count = values.parallelStream().sorted().count(); // parallel
System.out.println(count);
long t1 = System.nanoTime();
long milis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
System.out.println(String.format("sort took: %d ms", milis));
}
}
Map
import java.util.HashMap;
import java.util.Map;
public class MapDemo {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<>();
for (int i=0; i<10; i++) {
map.putIfAbsent(i, "val"+i);
}
map.forEach((id, val) -> System.out.println(val));
map.computeIfPresent(3, (num, val) -> val + num);
System.out.println(map.get(3));
map.computeIfPresent(9, (num, val) -> null);
System.out.println(map.containsKey(9));
map.computeIfAbsent(23, num -> "val"+num);
System.out.println(map.containsKey(23));
System.out.println(map.get(23));
map.computeIfAbsent(3, num -> "bam");
System.out.println(map.get(3));
map.remove(3, "val3");
System.out.println(map.get(3));
map.remove(3, "val33");
System.out.println(map.get(3));
System.out.println(map.getOrDefault(42, "Not Found"));
System.out.println(map.get(9));
map.merge(9, "val98", (value, newValue) ->
value.concat(newValue));
System.out.println(map.get(9));
map.merge(9, "concat", (value, newValue) ->
value.concat(newValue));
System.out.println(map.get(9));
}
}
九、Date API
import java.time.Clock;
import java.time.DayOfWeek;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Month;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.Locale;
public class DateDemo {
public static void main(String[] args) {
// Clock 时钟
Clock clock = Clock.systemDefaultZone();
long milis = clock.millis();
System.out.println("milis: " + milis);
long oldMilis = System.currentTimeMillis();
System.out.println("oldMilis: " + oldMilis);
System.out.println("milis compare oldMilis: " + (milis == oldMilis));
Instant instant = clock.instant();
Date legacyDate = Date.from(instant);
System.out.println("legacyDate: " + legacyDate);
Date oldDate = new Date();
System.out.println("oldDate: " + oldDate);
System.out.println("legacyDate compare oldDate: " + oldDate.equals(legacyDate));
// Timezones 时区
System.out.println(ZoneId.getAvailableZoneIds());
ZoneId zone1 = ZoneId.of("Europe/Berlin");
ZoneId zone2 = ZoneId.of("Brazil/East");
System.out.println(zone1.getRules());
System.out.println(zone2.getRules());
// LocalTime 本地时间
LocalTime now1 = LocalTime.now(zone1);
LocalTime now2 = LocalTime.now(zone2);
System.out.println(now1.isBefore(now2));
long hoursBetween = ChronoUnit.HOURS.between(now1, now2);
long minutesBetween = ChronoUnit.MINUTES.between(now1, now2);
System.out.println(hoursBetween);
System.out.println(minutesBetween);
LocalTime late = LocalTime.of(23, 59, 59);
System.out.println(late);
DateTimeFormatter germanFormatter =
DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT)
.withLocale(Locale.GERMAN);
LocalTime leetTime = LocalTime.parse("13:37", germanFormatter);
System.out.println(leetTime);
// LocalDate 本地日期
LocalDate today = LocalDate.now();
LocalDate tomorrow = today.plus(1, ChronoUnit.DAYS);
LocalDate yesterday = tomorrow.minusDays(2);
System.out.println("yesterday is: " + yesterday);
LocalDate independenceDay = LocalDate.of(2018, Month.JULY, 4);
DayOfWeek dayOfWeek = independenceDay.getDayOfWeek();
System.out.println(dayOfWeek);
DateTimeFormatter germanFormatter2 =
DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)
.withLocale(Locale.GERMAN);
LocalDate xmas = LocalDate.parse("25.08.2018", germanFormatter2);
System.out.println(xmas);
// LocalDateTime 本地日期时间
LocalDateTime localDateTime = LocalDateTime.of(2018, Month.MAY, 13, 20, 29, 28);
DayOfWeek dayOfWeek2 = localDateTime.getDayOfWeek();
System.out.println(dayOfWeek2); //SUNDAY
Month month = localDateTime.getMonth();
System.out.println(month); // MAY
long minuteOfDay = localDateTime.getLong(ChronoField.MINUTE_OF_DAY);
System.out.println(minuteOfDay); // 1229
Instant instant2 = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
Date legacyDate2 = Date.from(instant2);
System.out.println(legacyDate2); // Sun May 13 20:29:28 CST 2018
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
LocalDateTime parsed = LocalDateTime.parse("2018-05-13 08:38", formatter);
String string = formatter.format(parsed);
System.out.println(string); // 2018-05-13 08:38
}
}