1.Java8新特性编程风格
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Java8Tester {
public static void main(String[] args) {
List<Integer> list1 = new ArrayList<>();
list1.add(14);
list1.add(233);
list1.add(3232);
list1.add(23);
list1.add(90);
List<String> list2 = new ArrayList<>();
list2.add("google");
list2.add("baidu");
list2.add("taobao");
list2.add("jingdong");
list2.add("tiaomao");
java7TesterSort(list1);
System.out.println("java7 :"+list1);
java8TesterSort(list2);
System.out.println("java8 :"+list2);
}
private static void java7TesterSort(List<Integer> list1) {
Collections.sort(list1, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2);
}
});
}
private static void java8TesterSort(List<String> list1) {
Collections.sort(list1, (o1, o2) -> o1.compareTo(o2));
}
}
输出结果为:
ps:
1)运行main方法时,报了启动错误,
objc[63766]: Class JavaLaunchHelper is implemented in both /Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/bin/java (0x10390d4c0) and /Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home/jre/lib/libinstrument.dylib (0x1039e94e0). One of the two will be used. Which one is undefined.
解决方法:Help-->Edit Custom Properties-->Create 然后在idea.properties里增加
idea.no.launcher=true
问题解决
2)idea输出日志的快捷键与eclipse不同,IDEA使用sout ,Eclipse使用syso
2.Lambda表达式实例
public class Java8Tester {
public static void main(String[] args) {
MathOperaion add = (a, b) -> (a + b);
System.out.println(operate(1, 2, add));
SayHello sayHello=message -> System.out.println("Hello "+message);
sayHello.sayHello("hzb");
}
interface MathOperaion {
int operation(int a, int b);
}
interface SayHello{
void sayHello(String message);
}
private static int operate(int a, int b, MathOperaion mathOperaion) {
return mathOperaion.operation(a, b);
}
}
输出结果为:
public class Java8Tester {
public static void main(String[] args) {
int num = 1;
Convert<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num));
s.convert(2);
//num = 5;
}
interface Convert<T1, T2> {
void convert(int i);
}
}
返回结果为3,如放开注释num=5,更改局部变量,则出现异常,如下图所示:
说明:
lambda 表达式的局部变量可以不用声明为 final,但是必须不可被后面的代码修改(即隐性的具有 final 的语义)
在 Lambda 表达式当中不允许声明一个与局部变量同名的参数或者局部变量。
3. 双冒号 :: 的用法
import java.util.ArrayList;
import java.util.List;
public class Java8Tester {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("China");
list.add("America");
list.add("France");
list.add("Germany");
list.add("Italy");
list.forEach(Java8Tester::printStr);
}
public static void printStr(String str) {
System.out.println("输出结果为:" + str);
}
}
双冒号就是把方法当作参数传入stream内部,让stream的每一个元素都进入该方法执行,输出结果如下图所示:
Java8中,Iterable 实现了forEach方法,调用了Consumer 接口的accept方法,执行传入的方法参数,源码如下:
/**
* Performs the given action for each element of the {@code Iterable}
* until all elements have been processed or the action throws an
* exception. Unless otherwise specified by the implementing class,
* actions are performed in the order of iteration (if an iteration order
* is specified). Exceptions thrown by the action are relayed to the
* caller.
*
* @implSpec
* <p>The default implementation behaves as if:
* <pre>{@code
* for (T t : this)
* action.accept(t);
* }</pre>
*
* @param action The action to be performed for each element
* @throws NullPointerException if the specified action is null
* @since 1.8
*/
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
4.函数式接口Predicate<T>的用法
它接受一个输入参数T,返回一个boolean值,示例代码如下:
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
public class Java8Tester {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
System.out.println("输出所有参数:");
eval(list, n -> true);
System.out.println();
System.out.println("输出所有偶数:");
eval(list, n -> (n % 2 == 0));
System.out.println();
System.out.println("输出所有大于3的数:");
eval(list, n -> n > 3);
}
private static void eval(List<Integer> list, Predicate<Integer> predicate) {
//第一种方法
for (Integer n : list) {
if (predicate.test(n)) {
System.out.print(n + " ");
}
}
//第二种方法
list.stream().filter(predicate).forEach(System.out::print);
}
}
输出结果如下图所示:
ps:@FunctionalInterface主要用于编译级代码检查,对是不是函数式接口无影响,个人感觉等同于@Override
5.默认方法
参考链接:https://blog.csdn.net/tony308001970/article/details/81937765
6.Stream
stream():为集合创建串行流
parallel():为集合创建并行流
filter():筛选符合条件的元素
forEach():迭代流中的每个数据
map():映射到每个元素对应的结果(可以对元素进行处理并返回 如:map(x -> x*x).distinct())
sorted():排序
Collectors():使用了很多归约操作,将流转成集合和聚合元素
IntSummaryStatistics:收集器(max,min,average,sum)如mapToInt((x) -> x).summaryStatistics()
import java.util.Arrays;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
public class Java8Tester {
public static void main(String[] args) {
System.out.println("使用 Java 8: ");
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl");
System.out.println("列表: " + strings);
// 计算空字符串
long count = strings.stream().filter(s -> s.isEmpty()).count();
System.out.println("空字符数量为: " + count);
count = strings.stream().filter(s -> s.length() == 3).count();
System.out.println("字符串长度为 3 的数量为: " + count);
// 删除空字符串
List<String> filtered = strings.stream().filter(s -> !s.isEmpty()).collect(Collectors.toList());
System.out.println("筛选后的列表: " + filtered);
// 删除空字符串,并使用逗号把它们合并起来
String mergedString = strings.stream().filter(s -> !s.isEmpty()).collect(Collectors.joining(","));
System.out.println("合并字符串: " + mergedString);
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
// 获取列表元素平方数
List<Integer> squaresList = numbers.stream().map(i -> i * i).distinct().collect(Collectors.toList());
System.out.println("平方数列表: " + squaresList);
List<Integer> integers = Arrays.asList(1, 2, 13, 4, 15, 6, 17, 8, 19);
IntSummaryStatistics intSummaryStatistics = integers.stream().mapToInt(i -> i).summaryStatistics();
System.out.println("列表: " + integers);
System.out.println("列表中最大的数 : " + intSummaryStatistics.getMax());
System.out.println("列表中最小的数 : " + intSummaryStatistics.getMin());
System.out.println("所有数之和 : " + intSummaryStatistics.getSum());
System.out.println("平均数 : " + intSummaryStatistics.getAverage());
System.out.println("随机数: ");
Random random = new Random();
// 输出10个排序的随机数
random.ints().limit(10).sorted().forEach(System.out::println);
}
}
输出结果如下图所示:
7.Optional类
Optional类是个容器,可以保存类型T的值,可以很好的解决空指针异常
Optional.ofNullable(value):允许传递参数值为null
Optional.of(value):如果值为null,则抛出空指针异常NullPointerException
value.isPresent():判断值是否存在,如果存在返回true,否则返回false
value.orElse(value):如果值存在,返回此值,否则返回默认值
value.get():如果值存在,取得此值
import java.util.Optional;
public class Java8Tester {
public static void main(String[] args) {
Java8Tester java8Tester = new Java8Tester();
Integer value1 = null;
Integer value2 = new Integer(10);
//允许传递参数为null
Optional<Integer> optional1 = Optional.ofNullable(value1);
//如果值为null,则跑出空指针异常NullPointerException
Optional<Integer> optional2 = Optional.of(value2);
System.out.println(java8Tester.sum(optional1, optional2));
}
public Integer sum(Optional<Integer> value1, Optional<Integer> value2) {
System.out.println("第一个参数存在: " + value1.isPresent());
System.out.println("第二个参数存在: " + value2.isPresent());
//如果值存在则返回此值,否则返回默认值
Integer returnValue1 = value1.orElse(new Integer(0));
//取得存在的值
Integer returnValue2 = value2.get();
return returnValue1 + returnValue2;
}
}
输出结果如下图所示:
8.LocaLDateTime的使用
如果是JDK8的应用,可以使用Instant代替Date,LocalDateTime代替Calendar,DateTimeFormatter代替SimpleDateFormat,官方给出的解释: simple beautiful strong immutable thread-safe(简单优秀健壮不可变 线程安全)
使用Spring Boot时,使用LocalDatetime类时,接收前端传递的数据时,需要在参数之前加上@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")或者@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")注解,否则接收不到数据,而且会报错
如下是LocalDateTime和其他类型的转换工具类:
import org.apache.commons.lang.StringUtils;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
public class Java8Tester {
public static void main(String[] args) {
String dateStr = "2019-08-09 09:23:22";
LocalDateTime localDateTime = LocalDateTime.now();
Date date = new Date();
System.out.println("LocalDateTime类型:" + localDateTime);
System.out.println("LocalDateTime类型转成String类型:" + Java8Tester.localDateToStr(localDateTime, "yyyy-MM-dd"));
System.out.println("LocalDateTime类型转成Date类型:" + Java8Tester.localDateToDate(localDateTime));
System.out.println("Date类型转成LocalDateTime类型: " + Java8Tester.dateToLocalDateTime(date));
System.out.println("String类型转成LocalDateTime类型: " + Java8Tester.strToLocalDateTime(dateStr));
System.out.println("String类型转成Date类型: " + Java8Tester.strToDate(dateStr, "yyyy-MM-dd HH:mm:ss"));
}
/**
* LocalDateTime类型转成String类型
*
* @param localDateTime
* @param pattern
* @return
*/
public static String localDateToStr(LocalDateTime localDateTime, String pattern) {
try {
if (localDateTime != null && StringUtils.isNotBlank(pattern)) {
DateTimeFormatter df = DateTimeFormatter.ofPattern(pattern);
return df.format(localDateTime);
}
} catch (Exception e) {
e.printStackTrace();
}
return "";
}
/**
* LocalDateTime类型转成Date类型
*
* @param localDateTime
* @return
*/
public static Date localDateToDate(LocalDateTime localDateTime) {
//获取系统默认时区
ZoneId zoneId = ZoneId.systemDefault();
//将将此日期时间与时区组合以创建ZonedDateTime,并转成Instant类型
Instant instant = localDateTime.atZone(zoneId).toInstant();
//再将Instant类型转成Date类型
return Date.from(instant);
}
/**
* Date类型装成LocalDateTime类型
*
* @param date
* @return
*/
public static LocalDateTime dateToLocalDateTime(Date date) {
Instant instant = date.toInstant();
ZoneId zoneId = ZoneId.systemDefault();
return LocalDateTime.ofInstant(instant, zoneId);
}
/**
* String类型转成LocalDateTime类型
*
* @param dateStr
* @return
*/
public static LocalDateTime strToLocalDateTime(String dateStr) {
if (StringUtils.isEmpty(dateStr)) {
return null;
}
dateStr = dateStr.replace("T", " ").trim();
if (dateStr.contains("T") && dateStr.length() > 11) {
dateStr.replace("T", " ");
if (dateStr.length() == 16) {
dateStr = dateStr + ":00";
}
} else if (dateStr.contains("T") && dateStr.length() == 11) {
dateStr.replace("T", " 00:00:00");
} else if (dateStr.length() == 10) {
dateStr = dateStr + " 00:00:00";
}
Date date = Java8Tester.strToDate(dateStr, "yyyy-MM-dd HH:mm:ss");
if (null == date) {
return null;
}
return LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
}
/**
* String类型转成Date类型
*
* @param dateStr
* @param pattern
* @return
*/
public static Date strToDate(String dateStr, String pattern) {
if (StringUtils.isEmpty(dateStr)) {
return null;
}
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
Date date = null;
try {
date = sdf.parse(dateStr);
} catch (ParseException e) {
e.printStackTrace();
}
return date;
}
}
输出结果如下图所示:
9.Base64
UUID.randomUUID().toString()是javaJDK提供的一个自动生成主键的方法。UUID(Universally Unique Identifier)全局唯一标识符,是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的,是由一个十六位的数字组成,表现出来的形式。
Base64 编码 Encode:
Base64.getEncoder().encodeToString("hzb".getBytes()) :基本型Base64编码
Base64.getUrlEncoder().encodeToString("hzb".getBytes()) :URL型Base64编码
Base64.getMimeEncoder().encodeToString("hzb".getBytes()) :MIME型Base64编码
Base64 解码 Decode:
Base64.getDecoder().decode(base64EncodingString) :基本型Base64解码
Base64.getUrlDecoder().decode(base64EncodingString) :URL型Base64解码
Base64.getMimeDecoder().decode(base64EncodingString) :MIME型Base64解码
import java.io.UnsupportedEncodingException;
import java.util.Base64;
import java.util.UUID;
public class Java8Tester {
public static void main(String[] args) {
try {
String password = "hzb?java8Test";
//编码使用基本型 base64 编码方案
String base64EncodingString = Base64.getEncoder().encodeToString(password.getBytes());
System.out.println("未经过Base64加密的原始密码: " + password);
System.out.println(" 经过Base64加密的加密密码: " + base64EncodingString);
//解码
byte[] base64DecodedBytes = Base64.getDecoder().decode(base64EncodingString);
System.out.println(" 经过Base64解密的密码: " + new String(base64DecodedBytes, "utf-8"));
//编码使用 URL 和文件名安全型 base64 编码方案
String base64UrlEncodingString = Base64.getUrlEncoder().encodeToString(password.getBytes());
System.out.println(" 经过Base64加密的加密密码(URL): " + base64UrlEncodingString);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10; i++) {
sb.append(UUID.randomUUID().toString());
}
byte[] sbBytes = sb.toString().getBytes();
//编码使用 MIME 型 base64 编码方案
String base64MimeEncodingString = Base64.getMimeEncoder().encodeToString(sbBytes);
System.out.println(" 经过Base64加密的加密密码(MIME): " + base64MimeEncodingString);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
输出结果如下图所示: