接口的默认方法 default关键字
可以在接口中定义方法的默认实现,并且实现类也可以选择是否重新默认实现。
lambda表达式
新增了@FunctionalInterface注解,该注解添加在只有一个抽象方法的接口上,表示可以作为函数传入。如果被添加该注解的接口有多个抽象方法,则会编译不通过。
函数式编程
以前在使用像Comparator这种接口时,一般是使用匿名内部类来实现,还有就是实现Runable接口等。
1.8之前:
ArrayList students = new ArrayList<>(10);
students.sort(new Comparator() {
@Override
public int compare(Student o1, Student o2) {
return o1.getName().compareTo(o2.getName());
}
});
lambda:
ArrayList students = new ArrayList<>(10);
students.sort((Student o1,Student o2) -> o1.getName().compareTo(o2.getName()));
lambda简化:省去参数类型等定义
ArrayList students = new ArrayList<>(10);
students.sort((o1,o2) -> o1.getName().compareTo(o2.getName()));
使用Comparator的静态方法,传入比较的key的方法函数
ArrayList students = new ArrayList<>(10);
students.sort(Comparator.comparing(Student::getName));
引入lambda表达式后,可以使这种实现更为简单。
lambda表达式内可以对静态变量和对象变量进行读写,对局部变量只能够读,并且被表达式内读的局部变量在之后不能被改变(类似于final)。
双冒号::的使用
可以使用双冒号来访问类的构造函数,静态函数和对象函数.
- 构造函数:
定义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 creat(String nikename,String username);
}
访问构造函数
PersonFactory personFactory = Person::new;
Person person = personFactory.creat("羊肉小笼包", "大哥你好");
在上面的代码中,Person::new相当于create(String,String)方法的实现,而这个实现就是Person类的构造函数,相当于使用构造函数实现接口的唯一抽象方法。
-
静态方法
Person类中有一个静态方法run
public class Person { public static String run(){ return "Im running!"; } }
定义Action接口,内有一个抽象方法doThing
@FunctionalInterface public interface Action
{ T doThing(); } 测试
Action
run = Person::run; System.out.println(run.doThing()); // 打印出"Im running!" -
实例方法
Person类中有一个实例方法eat
public class Person { public String eat(String food){ return food + " is delicious!"; } }
定义接口LifeAction
@FunctionalInterface public interface LifeAction
{ T requiredAction(P something); } 测试
Person person = new Person(); LifeAction
eat = person::eat; System.out.println(eat.requiredAction("noodle")); // 打印noodle is delicious!
新增函数式接口
Predicate接口
@FunctionalInterface
public interface Predicate {
boolean test(T t);
default Predicate and(Predicate super T> other);
default Predicate negate();
default Predicate or(Predicate super T> other);
static Predicate isEqual(Object targetRef);
}
demo
private static boolean check(Integer num){
// 使用静态方法根据一个参数初始化
Predicate
Function接口
@FunctionalInterface
public interface Function {
R apply(T t);
default Function compose(Function super V, ? extends T> before);
default Function andThen(Function super R, ? extends V> after);
static Function identity();
}
demo
// 返回参数本身的function
Function
Supplier接口
Supplier
@FunctionalInterface
public interface Supplier {
T get();
}
demo
public class SupplierDemo {
public static void main(String[] args) {
Supplier supplier = SupplierDemo::new;
SupplierDemo supplierDemo = supplier.get();
Supplier a = SupplierDemo::a;
System.out.println(a.get());
//打印aaaa
}
public static String a(){
return "aaaa";
}
}
Suplier接口可以以任何无参数的类中方法作为实现,
当然无参数类中方法必须无重写方法。
Consumer接口
Consumer
这个接口就是封装了一个消费的操作,然后有一个对传入数据的二次消费的默认实现
@FunctionalInterface
public interface Consumer {
void accept(T t);
default Consumer 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 first = (o)-> System.out.println(o+"1");
Consumer second = first.andThen((o) -> System.out.println(o + ".....2"));
second.accept("parameter");
}
}
//打印
//parameter1
//parameter.....2
Comparator接口
该接口是1.2版本中添加的接口,这次1.8版本将这个接口添加了@FunctionInterface注解,并且添加了多个静态方法和默认实现。
具体请看另一篇文章:
Comparetor接口和Comparable接口的区别
集合的Stream操作
串行stream:Collection.stream
并行stream:Collection.parallelStream
使用集合的Stream操作是不影响原Collection的值的。
过滤元素
其中Filter方法的参数是Predicate接口,也就是判断逻辑
list.stream().filter(s -> s.startsWith("b")).forEach(System.out::println);
集合排序
sorted方法无参时是使用自然排序,如果有参,参数为Comparator接口
list.parallelStream().sorted().forEach(System.out::println);
list.parallelStream().sorted(String::compareTo).forEach(System.out::println);
集合迭代
forEach方法参数为Consumer接口
list.forEach(System.out::println);
list.stream().forEach(System.out::println);
list.parallelStream().forEach(System.out::println);
集合元素处理
map方法参数为Function接口,需要实现对集合元素处理逻辑,返回新的Stream
list.stream().map((String o)->Integer.valueOf(o.substring(3))).forEach(System.out::println);
结合元素匹配
类似于contain方法,Stream的match方法可以根据实现的匹配逻辑判断集合中是否含有该种元素。方法参数是Predicate接口,返回值是boolean。
全部匹配
list.stream().allMatch(o -> o.startsWith("a"))
是否存在匹配
list.stream().anyMatch(o->o.startsWith("a"));
无匹配
list.stream().noneMatch(o->o.startsWith("a"));
集合元素计数
list.stream.filter(s->s.startsWith("a").count())
集合计算
System.out.println(list.stream().reduce("head:", (o1, o2) -> o1 + o2));
// 打印出head:元素拼接
// 其中第一个参数是作为初始变量,作为o1传入了方法内
Optional类
一个封装泛型数据的容器,可以很方便的用来判断数据是否为null,可以作为方法的返回类型和方法入参。
demo
public static Optional getInstace(User str){
// 这种实例化方式参数可以为null
Optional strOption = Optional.ofNullable(str);
// 这种实例化方式参数不能为null,否则会报空指针异常
Optional str1 = Optional.of(str);
return strOption;
}
public static User orElse(User user){
// 可以在获得元素的时候有一个默认
Optional user1 = Optional.ofNullable(user);
User et = user1.orElse(new User("3", "ET"));
return et;
}
public static User orElseGet(User user){
// 在获取元素时如果为null,调用一个Supplier的实现构造一个新的元素
Optional user1 = Optional.ofNullable(user);
return user1.orElseGet(() -> new User("3", "ET"));
}
public static Optional filter(User user){
// 过滤容器内元素,使用predicate接口,如果test方法为false则返回一个空的容器
Optional user1 = Optional.ofNullable(user);
return user1.filter((o) -> o.getSex() == null);
}
新的时间日期API:
LocalDate
获取当前的date
// 获取指定zone现在的date
String s = LocalDate.now(ZoneId.of("America/Chicago")).toString();
// 获取当前地区现在的date
String s1 = LocalDate.now().toString();
// 获取当前zone现在的date
LocalDate.now(Clock.systemDefaultZone()).toString();
根据指定年月日获取localDate
// 根据指定的年月日生成localDate
LocalDate of = LocalDate.of(year, month, day);
// 这里是把月份int用枚举值代替
LocalDate of1 = LocalDate.of(year, Month.APRIL, day);
// 1970-01-01加上Long类型参数天的日期
String s = LocalDate.ofEpochDay(356 * 10L).toString();
获取当月的特殊日期
// 获取本月的第一天日期
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();
// 获取当前年份
int year1 = LocalDate.now().getYear();
// 获取当前月份
int month1 = LocalDate.now().getMonth().getValue();
LocalTime
与LocalDate类似
获取LocalTime实例
// 该实例会生成带有毫秒数的一个LocalTime
LocalTime now = LocalTime.now();
// 其参数为,时、分、秒、纳秒
LocalTime of = LocalTime.of(1, 2, 2, 3);
LocalTime of1 = LocalTime.of(1, 2, 3);
操作LocalTime实例
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之间的转化
LocalDateTime of1 = LocalDateTime.of(LocalDate.now(), LocalTime.now());
LocalDate localDate = of1.toLocalDate();
LocalTime localTime = of1.toLocalTime();
DateTimeFormatter
格式化LocalDate、LocalTime和LocalDateTime三个类,使用方式相同
转为格式String
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime now = LocalDateTime.now();
String format = now.format(dateTimeFormatter);
String转日期时间类
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是一个抽象类,在其内部有四个内部类:
- SystemClock
- FixedClock
- OffsetClock
- TickClock
支持多重注解
原来需要使用数据类型存储多个相同的注解,现在可以将多个形同注解加载同一处,给注解添加@Repatable元注解即可,
编译器会自动帮你将相同注解存储在注解的数组属性里面。