接口的默認(rèn)方法 default關(guān)鍵字
可以在接口中定義方法的默認(rèn)實(shí)現(xiàn)诸衔,并且實(shí)現(xiàn)類也可以選擇是否重新默認(rèn)實(shí)現(xiàn)。
lambda表達(dá)式
新增了@FunctionalInterface注解颇玷,該注解添加在只有一個(gè)抽象方法的接口上笨农,表示可以作為函數(shù)傳入。如果被添加該注解的接口有多個(gè)抽象方法帖渠,則會(huì)編譯不通過(guò)谒亦。
函數(shù)式編程
以前在使用像Comparator這種接口時(shí),一般是使用匿名內(nèi)部類來(lái)實(shí)現(xiàn)空郊,還有就是實(shí)現(xiàn)Runable接口等份招。
1.8之前:
ArrayList<Student> students = new ArrayList<>(10);
students.sort(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getName().compareTo(o2.getName());
}
});
lambda:
ArrayList<Student> students = new ArrayList<>(10);
students.sort((Student o1,Student o2) -> o1.getName().compareTo(o2.getName()));
lambda簡(jiǎn)化:省去參數(shù)類型等定義
ArrayList<Student> students = new ArrayList<>(10);
students.sort((o1,o2) -> o1.getName().compareTo(o2.getName()));
使用Comparator的靜態(tài)方法,傳入比較的key的方法函數(shù)
ArrayList<Student> students = new ArrayList<>(10);
students.sort(Comparator.comparing(Student::getName));
引入lambda表達(dá)式后狞甚,可以使這種實(shí)現(xiàn)更為簡(jiǎn)單锁摔。
lambda表達(dá)式內(nèi)可以對(duì)靜態(tài)變量和對(duì)象變量進(jìn)行讀寫(xiě),對(duì)局部變量只能夠讀哼审,并且被表達(dá)式內(nèi)讀的局部變量在之后不能被改變(類似于final)谐腰。
雙冒號(hào)::的使用
可以使用雙冒號(hào)來(lái)訪問(wèn)類的構(gòu)造函數(shù),靜態(tài)函數(shù)和對(duì)象函數(shù).
- 構(gòu)造函數(shù):
定義Person類
public class Person {
Person(String nikename,String username){
this.nikename=nikename;
this.username=username;
}
private String nikename;
private String username;
}
定義PersonFactory接口
@FunctionalInterface
public interface PersonFactory<P> {
P creat(String nikename,String username);
}
訪問(wèn)構(gòu)造函數(shù)
PersonFactory<Person> personFactory = Person::new;
Person person = personFactory.creat("羊肉小籠包", "大哥你好");
在上面的代碼中涩盾,Person::new相當(dāng)于create(String,String)方法的實(shí)現(xiàn)十气,而這個(gè)實(shí)現(xiàn)就是Person類的構(gòu)造函數(shù),相當(dāng)于使用構(gòu)造函數(shù)實(shí)現(xiàn)接口的唯一抽象方法旁赊。
-
靜態(tài)方法
Person類中有一個(gè)靜態(tài)方法run
public class Person { public static String run(){ return "Im running!"; } }
定義Action接口桦踊,內(nèi)有一個(gè)抽象方法doThing
@FunctionalInterface public interface Action<T>{ T doThing(); }
測(cè)試
Action<String> run = Person::run; System.out.println(run.doThing()); // 打印出"Im running!"
-
實(shí)例方法
Person類中有一個(gè)實(shí)例方法eat
public class Person { public String eat(String food){ return food + " is delicious!"; } }
定義接口LifeAction
@FunctionalInterface public interface LifeAction<T,P> { T requiredAction(P something); }
測(cè)試
Person person = new Person(); LifeAction<String, String> eat = person::eat; System.out.println(eat.requiredAction("noodle")); // 打印noodle is delicious!
新增函數(shù)式接口
Predicate接口
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
default Predicate<T> and(Predicate<? super T> other);
default Predicate<T> negate();
default Predicate<T> or(Predicate<? super T> other);
static <T> Predicate<T> isEqual(Object targetRef);
}
demo
private static boolean check(Integer num){
// 使用靜態(tài)方法根據(jù)一個(gè)參數(shù)初始化
Predicate<Object> equal = Predicate.isEqual(num);
// 使用一個(gè)lambda表達(dá)式初始化
Predicate<Integer> checkNum = (i)->i>1;
// 將兩種判斷取邏輯或(有短路)default方法
Predicate<Integer> or = checkNum.or((i -> i < -1));
// 將兩種判斷取邏輯與(有短路)default方法
Predicate<Integer> and = or.and((i) -> i == 1);
// 將判斷取反
Predicate<Integer> negate = and.negate();
return or.test(num);
}
Function接口
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
default <V> Function<V, R> compose(Function<? super V, ? extends T> before);
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after);
static <T> Function<T, T> identity();
}
demo
// 返回參數(shù)本身的function
Function<Object, Object> identity = Function.identity();
// 定義一個(gè)有邏輯的function
Function<String, String> a = (s)->s+" 11111111";
// 定義一個(gè)有后續(xù)邏輯的function,先執(zhí)行的function的返回值
// 就是后執(zhí)行的function的參數(shù)终畅,類型需要匹配
Function<String, String> function = a.andThen((s) -> s+" 33333333");
// 定義一個(gè)有前置邏輯的function籍胯,前置執(zhí)行的function的
// 返回值就是該function的參數(shù)
Function<Object, String> compose = a.compose((s) -> s + " 222222");
Supplier接口
Supplier
@FunctionalInterface
public interface Supplier<T> {
T get();
}
demo
public class SupplierDemo {
public static void main(String[] args) {
Supplier<SupplierDemo> supplier = SupplierDemo::new;
SupplierDemo supplierDemo = supplier.get();
Supplier<String> a = SupplierDemo::a;
System.out.println(a.get());
//打印aaaa
}
public static String a(){
return "aaaa";
}
}
Suplier接口可以以任何無(wú)參數(shù)的類中方法作為實(shí)現(xiàn),
當(dāng)然無(wú)參數(shù)類中方法必須無(wú)重寫(xiě)方法离福。
Consumer接口
Consumer
這個(gè)接口就是封裝了一個(gè)消費(fèi)的操作杖狼,然后有一個(gè)對(duì)傳入數(shù)據(jù)的二次消費(fèi)的默認(rèn)實(shí)現(xiàn)
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
demo:
public class ConsumerDemo {
public static void main(String[] args) {
Consumer<String> first = (o)-> System.out.println(o+"1");
Consumer<String> second = first.andThen((o) -> System.out.println(o + ".....2"));
second.accept("parameter");
}
}
//打印
//parameter1
//parameter.....2
Comparator接口
該接口是1.2版本中添加的接口,這次1.8版本將這個(gè)接口添加了@FunctionInterface注解妖爷,并且添加了多個(gè)靜態(tài)方法和默認(rèn)實(shí)現(xiàn)蝶涩。
具體請(qǐng)看另一篇文章:
Comparetor接口和Comparable接口的區(qū)別
集合的Stream操作
串行stream:Collection.stream
并行stream:Collection.parallelStream
使用集合的Stream操作是不影響原Collection的值的理朋。
過(guò)濾元素
其中Filter方法的參數(shù)是Predicate接口,也就是判斷邏輯
list.stream().filter(s -> s.startsWith("b")).forEach(System.out::println);
集合排序
sorted方法無(wú)參時(shí)是使用自然排序绿聘,如果有參嗽上,參數(shù)為Comparator接口
list.parallelStream().sorted().forEach(System.out::println);
list.parallelStream().sorted(String::compareTo).forEach(System.out::println);
集合迭代
forEach方法參數(shù)為Consumer接口
list.forEach(System.out::println);
list.stream().forEach(System.out::println);
list.parallelStream().forEach(System.out::println);
集合元素處理
map方法參數(shù)為Function接口,需要實(shí)現(xiàn)對(duì)集合元素處理邏輯熄攘,返回新的Stream
list.stream().map((String o)->Integer.valueOf(o.substring(3))).forEach(System.out::println);
結(jié)合元素匹配
類似于contain方法兽愤,Stream的match方法可以根據(jù)實(shí)現(xiàn)的匹配邏輯判斷集合中是否含有該種元素。方法參數(shù)是Predicate接口,返回值是boolean挪圾。
全部匹配
list.stream().allMatch(o -> o.startsWith("a"))
是否存在匹配
list.stream().anyMatch(o->o.startsWith("a"));
無(wú)匹配
list.stream().noneMatch(o->o.startsWith("a"));
集合元素計(jì)數(shù)
list.stream.filter(s->s.startsWith("a").count())
集合計(jì)算
System.out.println(list.stream().reduce("head:", (o1, o2) -> o1 + o2));
// 打印出head:元素拼接
// 其中第一個(gè)參數(shù)是作為初始變量浅萧,作為o1傳入了方法內(nèi)
Optional類
一個(gè)封裝泛型數(shù)據(jù)的容器,可以很方便的用來(lái)判斷數(shù)據(jù)是否為null哲思,可以作為方法的返回類型和方法入?yún)ⅰ?/p>
demo
public static Optional<User> getInstace(User str){
// 這種實(shí)例化方式參數(shù)可以為null
Optional<User> strOption = Optional.ofNullable(str);
// 這種實(shí)例化方式參數(shù)不能為null洼畅,否則會(huì)報(bào)空指針異常
Optional<User> str1 = Optional.of(str);
return strOption;
}
public static User orElse(User user){
// 可以在獲得元素的時(shí)候有一個(gè)默認(rèn)
Optional<User> user1 = Optional.ofNullable(user);
User et = user1.orElse(new User("3", "ET"));
return et;
}
public static User orElseGet(User user){
// 在獲取元素時(shí)如果為null,調(diào)用一個(gè)Supplier的實(shí)現(xiàn)構(gòu)造一個(gè)新的元素
Optional<User> user1 = Optional.ofNullable(user);
return user1.orElseGet(() -> new User("3", "ET"));
}
public static Optional<User> filter(User user){
// 過(guò)濾容器內(nèi)元素棚赔,使用predicate接口帝簇,如果test方法為false則返回一個(gè)空的容器
Optional<User> user1 = Optional.ofNullable(user);
return user1.filter((o) -> o.getSex() == null);
}
新的時(shí)間日期API:
LocalDate
獲取當(dāng)前的date
// 獲取指定zone現(xiàn)在的date
String s = LocalDate.now(ZoneId.of("America/Chicago")).toString();
// 獲取當(dāng)前地區(qū)現(xiàn)在的date
String s1 = LocalDate.now().toString();
// 獲取當(dāng)前zone現(xiàn)在的date
LocalDate.now(Clock.systemDefaultZone()).toString();
根據(jù)指定年月日獲取localDate
// 根據(jù)指定的年月日生成localDate
LocalDate of = LocalDate.of(year, month, day);
// 這里是把月份int用枚舉值代替
LocalDate of1 = LocalDate.of(year, Month.APRIL, day);
// 1970-01-01加上Long類型參數(shù)天的日期
String s = LocalDate.ofEpochDay(356 * 10L).toString();
獲取當(dāng)月的特殊日期
// 獲取本月的第一天日期
LocalDate firstDay = LocalDate.now().with(TemporalAdjusters.firstDayOfMonth());
// 獲取本月的最后一天
LocalDate lastDay = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth());
// 今天是本月幾日
int dayOfMonth = LocalDate.now().getDayOfMonth();
// 今天是周幾
int value = LocalDate.now().getDayOfWeek().getValue();
// 獲取當(dāng)前年份
int year1 = LocalDate.now().getYear();
// 獲取當(dāng)前月份
int month1 = LocalDate.now().getMonth().getValue();
LocalTime
與LocalDate類似
獲取LocalTime實(shí)例
// 該實(shí)例會(huì)生成帶有毫秒數(shù)的一個(gè)LocalTime
LocalTime now = LocalTime.now();
// 其參數(shù)為,時(shí)忆嗜、分己儒、秒、納秒
LocalTime of = LocalTime.of(1, 2, 2, 3);
LocalTime of1 = LocalTime.of(1, 2, 3);
操作LocalTime實(shí)例
LocalTime now = LocalTime.now();
LocalTime localTime = now.plusHours(1);
LocalTime localTime1 = now.withMinute(12);
LocalTime localTime2 = localTime1.withHour(1);
LocalDateTime
該類包含了LocalDate和LocalTime的一些方法捆毫,如getMonth闪湾,getHour等。
LocalDate绩卤、LocalTime和LocalDateTime之間的轉(zhuǎn)化
LocalDateTime of1 = LocalDateTime.of(LocalDate.now(), LocalTime.now());
LocalDate localDate = of1.toLocalDate();
LocalTime localTime = of1.toLocalTime();
DateTimeFormatter
格式化LocalDate途样、LocalTime和LocalDateTime三個(gè)類,使用方式相同
轉(zhuǎn)為格式String
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime now = LocalDateTime.now();
String format = now.format(dateTimeFormatter);
String轉(zhuǎn)日期時(shí)間類
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String dateTimeStr = "1992-11-02 11:32:23";
TemporalAccessor parse = dateTimeFormatter.parse(dateTimeStr);
LocalDateTime from = LocalDateTime.from(parse);
Clock
Clock是一個(gè)抽象類濒憋,在其內(nèi)部有四個(gè)內(nèi)部類:
- SystemClock
- FixedClock
- OffsetClock
- TickClock
支持多重注解
原來(lái)需要使用數(shù)據(jù)類型存儲(chǔ)多個(gè)相同的注解何暇,現(xiàn)在可以將多個(gè)形同注解加載同一處,給注解添加@Repatable元注解即可凛驮,
編譯器會(huì)自動(dòng)幫你將相同注解存儲(chǔ)在注解的數(shù)組屬性里面裆站。