java9已经发布一段时间了,AndroidStudio才开始支持Java 8,Java 8是Java的一个重大版本,虽然这些新特性令Java开发人员十分期待,但同时也需要花不少精力去学习,对于android开发者而言了解Java8的新特性是必要的,虽然现在Google力推kotlin,但是Java仍然是排名第一的使用最广泛的语言,社区依旧很活跃,也是处于不断进步和发展中,而且在新特性中我们能看到一些kotlin的影子。
lambda表达式的支持
格式为:(入参) -> {函数体}
基本形式:
入参和返回值的类型可被编译器推测,入参一个参数不需要括号,无参直接写为()
,函数体多行可加上括号
1 2 3
| (int a, int b) -> a + b; (a, b) -> a - b; (int a, int b) -> { return a * b; };
|
用法:
for循环
以前的写法:
1 2 3
| for (String player : players) { System.out.print(player + "; "); }
|
lambda写法:
1
| players.forEach((player) -> System.out.print(player + "; "));
|
ui回调
以前的写法:
1 2 3 4 5 6
| check_all.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { } });
|
lambda写法:
1
| check_all.setOnClickListener(v->{});
|
创建线程
以前的写法:
1 2 3 4 5 6
| new Thread(new Runnable() { @Override public void run() { System.out.println("Hello world !"); } }).start();
|
lambda写法:
1
| new Thread(() -> System.out.println("Hello world !")).start();
|
排序
以前的写法:
1 2 3 4 5 6
| Arrays.sort(players, new Comparator<String>() { @Override public int compare(String s1, String s2) { return (s1.length() - s2.length()); } });
|
lambda写法:
1
| Arrays.sort(players, (String s1, String s2) -> (s1.length() - s2.length()));
|
结合Stream
Stream是对集合的包装,通常和lambda一起使用。 使用lambdas可以支持许多操作,如 map, filter, limit, sorted, count, min, max, sum, collect 等等。
定义一个类,医生
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| public class Doctor { private String name; private int age; private String degree; private int salary;
public Doctor(String name, int age, String degree, int salary) { this.name = name; this.age = age; this.degree = degree; this.salary = salary; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public String getDegree() { return degree; }
public void setDegree(String degree) { this.degree = degree; }
public int getSalary() { return salary; }
public void setSalary(int salary) { this.salary = salary; } }
|
先初始化医生列表,foreach循环输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| List<Doctor> doctors =new ArrayList<>(); doctors.add(new Doctor("joe",20,"bachelor",2000)); doctors.add(new Doctor("jack",23,"bachelor",2300)); doctors.add(new Doctor("kris",27,"Master",4200)); doctors.add(new Doctor("bob",28,"doctor",5000)); doctors.add(new Doctor("tom",26,"Master",4400)); doctors.add(new Doctor("jay",29,"doctor",5500));
doctors.forEach( (doctor)->{ System.out.println(doctor.getName());
} );
|
过滤器filter(),过滤出年龄大于25岁且学历为博士的医生
1 2 3
| doctors.stream().filter( doctor -> doctor.getAge()>25) .filter(doctor -> "doctor".equals(doctor.getDegree())) .forEach(doctor -> System.out.println(doctor.getName()));
|
limit方法,限制结果个数,年龄大于25的前三个医生
1 2 3
| doctors.stream().filter( doctor -> doctor.getAge()>25) .limit(3) .forEach(doctor -> System.out.println(doctor.getName()));
|
sorted方法,按薪水由多到少排序
1 2 3 4 5 6
| doctors.stream().sorted((d1,d2)->d2.getSalary()-d1.getSalary()) .forEach( (doctor)->{ System.out.println(doctor.getName()); } );
|
min和max方法,找出最低和最高的薪水
1 2 3 4 5
| Doctor doctor1=doctors.stream().min((d1,d2)->d1.getSalary()-d2.getSalary()).get(); System.out.print(doctor1.getName());
Doctor doctor2=doctors.stream().min((d1,d2)->d1.getSalary()-d2.getSalary()).get(); System.out.print(doctor2.getName());
|
结合 map 方法,使用 collect 方法来将我们的结果集放到一个字符串,一个 Set 中
将所有医生的名字拼接在一个string中,用逗号隔开
1 2
| String names=doctors.stream().map(Doctor::getName).collect(joining(",")); System.out.print(names);
|
将所有医生的名字存放到一个set中
1 2
| Set<String> doctorSet=doctors.stream().map(Doctor::getName).collect(Collectors.toSet()); octorSet.forEach((name)->System.out.println(name));
|
summaryStatistics方法获得stream中元素的汇总数据,求和,平均值,最大最小值,个数
1 2 3 4 5 6 7 8
| IntSummaryStatistics statistics=doctors.stream() .mapToInt(doctor->doctor.getSalary()) .summaryStatistics(); System.out.println(statistics.getSum()); System.out.println(statistics.getAverage()); System.out.println(statistics.getMax()); System.out.println(statistics.getMin()); System.out.println(statistics.getCount());
|
接口的默认方法和静态方法
默认方法和抽象方法之间的区别在于抽象方法需要实现,而默认方法不需要。接口提供的默认方法可以被接口的实现类继承或者覆写。
1 2 3 4 5 6 7 8 9
| public interface MyInterface{ default String defaultMethod(){ return "this is default method"; } }
public class MyClass implements MyInterface{ }
|
在接口中可以定义静态方法
1 2 3 4 5 6 7 8
| public interface MyInterface{ default String defaultMethod(){ return "this is default method"; } static String staticMethod(){ return "this is static method"; } }
|
方法的引用方式
初始化数组
1 2 3 4 5 6
| Function<Integer, String[]> fun = x -> new String[x]; String[] strs = fun.apply(10); System.out.println(strs.length); Function<Integer,String[]> fun1 = String[]::new; strs = fun1.apply(20); System.out.println(strs.length);
|
构造方法的引用 Class::new只针对无参构造,若该类只有有参构造,需要添加一个无参构造方法:
1 2 3 4
| Supplier<Student> supplier=Student::new; Student student=supplier.get(); student.setName("小明"); System.out.println(student.getName());
|
有参构造调用
1 2 3
| Supplier<Student> supplier=()->new Student("小张","man",12); Student student=supplier.get(); System.out.println(student.getName());
|
静态方法调用
1 2
| Supplier<String> supplier=Student::saying; System.out.println(supplier.get());
|
成员方法调用
1 2 3 4 5 6 7
| Supplier<Student> supplier=Student::new; Student student=supplier.get(); Consumer<String> consumer1=student::setName; consumer1.accept("小明"); Consumer<Integer> consumer2=student::setAge; consumer2.accept(18); System.out.println(student.getName()+":"+student.getAge());
|
注解的变化
支持重复注解
1 2 3 4
| @Filter( "filter1" ) @Filter( "filter2" ) public interface Filterable { }
|
调用
1
| Filterable.class.getAnnoation(Filters.class)
|
控制台输出:
filter1
filter2
注解使用范围扩大
java8可以使用在任何元素上:局部变量、方法、接口、类和泛型,甚至可以用在函数的异常定义上。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @Retention( RetentionPolicy.RUNTIME ) @Target( { ElementType.TYPE_USE, ElementType.TYPE_PARAMETER } ) public @interface NonEmpty { }
public static class Holder< @NonEmpty T > extends @NonEmpty Object { public void method() throws @NonEmpty Exception { } }
@SuppressWarnings( "unused" ) public static void main(String[] args) { final Holder< String > holder = new @NonEmpty Holder< String >(); @NonEmpty Collection< @NonEmpty String > strings = new ArrayList<>(); }
|
Map新增方法
初始化一个map
1 2 3 4
| Map<Integer, String> map = new HashMap<>(); map.put(1, "Tom"); map.put(2, "Bob"); map.put(3, "Jack");
|
forEach 遍历
1
| map.forEach((key,value)->System.out.println(key+":"+value));
|
getOrDefault
如果指定的key存在,则返回该key对应的value,如果不存在,则返回指定的值。
1
| System.out.println(map.getOrDefault(4, "name"));
|
replaceAll修改所有的value值
1 2 3
| map.replaceAll((key,value)->"20000"+key+value); map.forEach((key,value)->System.out.println(key+":"+value));
|
putIfAbsent返回key对应的value,如果value为空则填入一个值
1 2 3 4 5 6
| map.putIfAbsent(3, "xiaoming"); map.putIfAbsent(4, "xiaoming");
System.out.println(map.get(3));
System.out.println(map.get(4));
|
remove指定元素删除
如果key获取的value值与给的value值相等,则删除这个元素
1 2 3 4 5 6 7
| map.remove(1, "Bob");
System.out.println(map.get(1));
map.remove(2, "Bob");
System.out.println(map.get(2))
|
replace替换
如果key获取的value值与给的value值相等,则把这个value替换成一个新的value
1 2 3 4 5 6
| map.replace(3, "Tom", "Joe");
System.out.println(map.get(3)); map.replace(1, "Tom", "Joe");
System.out.println(map.get(1));
|
如果map中存在key,则替换成value值,替换成功返回旧值,否则返回null
1 2 3 4 5 6 7 8
| System.out.println( map.replace(1, "Joe"));
System.out.println( map.get(1));
System.out.println( map.replace(4, "Joe"));
System.out.println( map.get(4));
|
computeIfAbsent
如果指定的key不存在,则可通过key计算value为新的值
1 2 3 4 5 6
| map.computeIfAbsent(1,key->key+"newName");
System.out.println(map.get(1)); map.computeIfAbsent(4,key->key+"newName");
System.out.println(map.get(4));
|
computeIfPresent
如果指定的key存在,则根据key和value计算一个新的newValue, 如果这个newValue不为null,则设置key新的值为这个newValue, 如果newValue为null, 则删除该key的值
1 2 3 4 5 6 7
| map.computeIfPresent(1, (key, value) -> key + "新的值:" + value);
System.out.println(map.get(1));
map.computeIfPresent(2, (key, value) -> null);
System.out.println(map.get(2));
|
compute
如果指定的key不存在,则设置指定的value值,否则根据key和value计算一个新的newValue, 如果这个newValue不为null,则设置key新的值为这个newValue, 如果newValue为null, 则删除该key的值。
这个解释有点长,容易绕,实际上用if-else可以很简单的表达
1 2 3 4 5 6
| if(!key.exist()){ map.computeIfAbsent(key,key->key+"newValue"); } else{ map.computeIfPresent(key, (key, value) -> key + "新的值:" + value); }
|
所以就是if key不存在,调computeIfAbsent,否则调computeIfPresent
1 2 3 4 5 6
| map.compute(4,(key,value)->key+":"+value+"新的值");
System.out.println(map.get(4)); map.compute(1,(key,value)->key+":"+"新的值");
System.out.println(map.get(1));
|
merge
如果指定的key不存在,直接设置指定值,如果存在根据旧的value,指定值计算出新的值newValue, 如果这个newValue不为空,设置key的新值newValue,如果newValue为null, 则删除该key。最后返回当前最新的值
1 2 3 4 5 6
| System.out.println(map.merge(4,"指定的名字",(oldValue,assignValue)->oldValue+","+assignValue));
System.out.println(map.merge(1,"指定的名字",(oldValue,assignValue)->oldValue+","+assignValue));
System.out.println(map.merge(1,"指定的名字",(oldValue,assignValue)->null));
|
空指针判断类Optional
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| String str1=null; String str2="abc";
Optional<String> optionalStr1=Optional.ofNullable(str1);
Optional<String> optionalStr2=Optional.of(str2); System.out.println("第一个参数是否存在"+optionalStr1.isPresent()); System.out.println("第二个参数是否存在"+optionalStr2.isPresent());
String getStr1=optionalStr1.orElse("这个值不存在的默认值");
String getStr2=optionalStr2.get(); System.out.println(getStr1); System.out.println(getStr2);
|
日期和时间Joda-Time的支持
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| LocalDateTime currentTime = LocalDateTime.now(); System.out.println("当前时间: " + currentTime);
LocalDate currentDate = currentTime.toLocalDate(); System.out.println("当前日期: " + currentDate); System.out.println("年"+currentDate.getYear()+"月"+currentDate.getMonthOfYear()+"日"+currentDate.getDayOfMonth());
currentDate.withYear(2013).withMonthOfYear(3); System.out.println("修改后的日期: " + currentDate);
System.out.println(currentDate.toString("yyyy-MM-dd"));
DateTimeZone zoneEurope = DateTimeZone.forID("Europe/London"); DateTime dtLondon = new DateTime().withZone(zoneEurope); System.out.println("修改时区: " + dtLondon); DateTimeZone currentZone = DateTimeZone.getDefault(); DateTime dtCurrent = new DateTime().withZone(currentZone); System.out.println("当期时区: " + dtCurrent);
|
base64支持
基本编解码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| try { String base64encodedString = Base64.getEncoder().encodeToString("这是待编码的字符串".getBytes("utf-8")); System.out.println("Base64编码后" + base64encodedString); byte[] base64decodedBytes = Base64.getDecoder().decode(base64encodedString); System.out.println("原始字符串: " + new String(base64decodedBytes, "utf-8")); String base64encodedUrl = Base64.getUrlEncoder().encodeToString("这是待编码的字符串".getBytes("utf-8")); System.out.println("Base64 URL编码:" + base64encodedUrl); StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < 1; ++i) { stringBuilder.append(UUID.randomUUID().toString()); } byte[] mimeBytes = stringBuilder.toString().getBytes("utf-8"); String mimeEncodedString = Base64.getMimeEncoder().encodeToString(mimeBytes); System.out.println("Base64 MIME编码:" + mimeEncodedString); }catch(UnsupportedEncodingException e){ System.out.println("Error :" + e.getMessage()); }
|