JDK变更
JDK新特性
JDK8
default关键字
public interface DefaultKey {
void test(String params);
default void sout(){
System.out.println("default方法");
}
static void staticmd(){
System.out.println("static方法");
}
}
Base64
import java.io.UnsupportedEncodingException;
import java.util.Base64;
public class Base64Demo {
public static void main(String[] args) throws UnsupportedEncodingException {
Base64.Decoder decoder = Base64.getDecoder();
Base64.Encoder encoder = Base64.getEncoder();
String text = "⼩滴课堂";
byte[] textByte = text.getBytes("UTF-8");
//编码
String encodedText = encoder.encodeToString(textByte);
System.out.println(encodedText);
//解码
System.out.println(new String(decoder.decode(encodedText), "UTF-8"));
}
}
Date
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class DateDemo {
public static void main(String[] args) {
//LocalDate、LocalTime、LocalDateTime
LocalDateTime today = LocalDateTime.now();
System.out.println(today.getYear()+"年"+"|"+today.getMonth()+"|"+today.getMonthValue()+"月"+"|"+
today.getDayOfMonth()+"日"+"|"+"周几"+today.getDayOfWeek());
LocalDateTime afterYear = today.plusYears(1);
System.out.println(afterYear.getYear()+"年"+"|"+today.getMonth()+"|"+today.getMonthValue()+"月"+"|"+
today.getDayOfMonth()+"日"+"|"+"周几"+today.getDayOfWeek());
//withYear(int year) LocalDate 修改当前对象的年份
//withMonth(int month) LocalDate 修改当前对象的⽉份
//withDayOfMonth(int dayOfMonth) LocalDate 修改当前对象在当⽉的⽇期
//plusYears(long yearsToAdd) LocalDate 当前对象增加指定的年份数
//plusMonths(long monthsToAdd) LocalDate 当前对象增加指定的⽉份数
//plusWeeks(long weeksToAdd) LocalDate 当前对象增加指定的周数
//plusDays(long daysToAdd) LocalDate 当前对象增加指定的天数
//minusYears(long yearsToSubtract) LocalDate 当前对象减去指定的年数
//minusMonths(long monthsToSubtract) LocalDate 当前对象减去注定的⽉数
//minusWeeks(long weeksToSubtract) LocalDate 当前对象减去指定的周数
//minusDays(long daysToSubtract) LocalDate 当前对象减去指定的天数
//比较
//compareTo(ChronoLocalDate other) int ⽐较当前对象和other对象在时间上的⼤⼩,返回值如果为正,则当前对象时间较晚,
//isBefore(ChronoLocalDate other) boolean ⽐较当前对象⽇期是否在other对象⽇期之前
//isAfter(ChronoLocalDate other) boolean ⽐较当前对象⽇期是否在other对象⽇期之后
//isEqual(ChronoLocalDate other) boolean ⽐较两个⽇期对象是否相等
System.out.println(today.plusMonths(11).isBefore(afterYear));
//时间格式化
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(dtf.format(today));
//获取指定日期
LocalDateTime ldt = LocalDateTime.of(2020, 11, 11, 8, 20, 30);
System.out.println(ldt);
//时间间隔类
LocalDateTime today1 = LocalDateTime.now();
System.out.println(today1);
LocalDateTime changeDate = LocalDateTime.of(2020,10,1,10,40,30);
System.out.println(changeDate);
Duration duration = Duration.between( today1,changeDate);//第⼆个参数减第⼀个参数
System.out.println(duration.toDays());//两个时间差的天数
System.out.println(duration.toHours());//两个时间差的⼩时数
System.out.println(duration.toMinutes());//两个时间差的分钟数
System.out.println(duration.toMillis());//两个时间差的毫秒数
System.out.println(duration.toNanos());//两个时间差的纳秒数
}
}
Optional
import java.util.Optional;
public class OptionalDemo {
public static void main(String[] args) {
//of不能传空,ofNullable可能为空
Optional optional = Optional.of("fdssf");
Optional optional1 = Optional.ofNullable(null);
//兜底
int i = (int) Optional.ofNullable(6).orElse(7);
System.out.println(i);
}
}
lambda
自定义函数式编程
- 自定义lambda接口流程
- 定义一个函数式接口,需要标注接口@FunctionInterface,防止其他人在该接口增加其他方法
- 编写一个方法,输入需要操作的数据和接口
- 在调用方法前,传入数据和lambda
@FunctionalInterface
public interface OperFunction<R,T> {
R operator(T t1,T t2);
}
public class OperFunctionDemo {
public static void main(String[] args) {
System.out.println(operator(3,4,(x,y)->x+y));
}
public static Integer operator(Integer x, Integer y,OperFunction<Integer,Integer> of){
return of.operator(x,y);
}
}
jdk8内置函数式编程接口
java8 内置的四大核心函数式接口
Consumer<T> : 消费型接口
void accept(T t);
Supplier<T> : 供给型接⼝:⽆⼊参,有返回值
T get();
Function<T, R> : 函数型接⼝:有⼊参,有返回值
R apply(T t);
Predicate<T> : 断⾔型接⼝:有⼊参,有返回值,返回值类型确定是boolean
boolean test(T t);
方法的调用方式和构造函数引用
说明:操作符::用来直接访问类或者实例已经存在的方法或构造方法
静态方法:ClassName::methodName
实例方法:Instance::methodName
构造函数,ClassName::new
集合
import java.util.Arrays;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class StreamDemo {
public static void main(String[] args) {
List<String> list = Arrays.asList("abc","cda","bcd","abcd","efgh");
//流 map转换、filter过滤、排序、截断流、匹配、最大最小
System.out.println(list.stream().map(obj->"prefix"+obj).collect(Collectors.toList()));
System.out.println(list.stream().filter( obj->(obj.startsWith("a")||obj.startsWith("c")) ).collect(Collectors.toList()));
System.out.println(list.stream().sorted((a,b)->a.compareTo(b)).collect(Collectors.toList()));
System.out.println(list.stream().limit(2).collect(Collectors.toList()));
System.out.println(list.stream().allMatch(obj->obj.length()==3));
System.out.println(list.stream().anyMatch(obj->obj.equalsIgnoreCase("abc")));
System.out.println(list.stream().max((a,b)->a.compareTo(b)));
System.out.println(list.stream().min((a,b)->a.compareTo(b)));
//reduce 根据⼀定的规则将Stream中的元素进⾏计算后返回⼀个唯⼀的值
System.out.println(list.stream().reduce((a,b)->a+b));
System.out.println(list.stream().reduce("start||",(a,b)->a+b));
//并行流,存在线程安全问题
List list1 = new CopyOnWriteArrayList();
IntStream.range(1,100).parallel().forEach(list1::add);
System.out.println(list1);
list.forEach(System.out::println);
//收集器
//拼接
System.out.println(list.stream().collect(Collectors.joining(",","[","]")));
//分组
System.out.println(list.stream().collect(Collectors.partitioningBy(obj->obj.equalsIgnoreCase("abc"))));
System.out.println(list.stream().collect(Collectors.groupingBy(String::length)));
System.out.println(list.stream().collect(Collectors.groupingBy(String::length,Collectors.counting())));
//summarizing统计相关的提供 平均值、人数、最大值、最小值、总和
IntSummaryStatistics summaryStatistics = list.stream().collect(Collectors.summarizingInt(String::length));
System.out.println("平均值:"+summaryStatistics.getAverage());
}
}
jdk8新空间
-
JVM种类很多,比如Oracle-Sun Hotspot,Oracle JRockit ,IBM J9 ,Taobao JVM, Hotspot新增元空间(metaspace)
-
jdk8之前叫永久代(permanent generation),通过在命令行设置参数-XX:MaxPermSize来设定永久代最大可分配内存
如果JDK8设置了PermSize 和 MaxPermSize 会被忽略和警告
-
作用:该块内存主要用来存放class和mate信息,当class被加载loader的时候就i会被存储到该内存中,如方法的编译信息及字节码、常量池和符号解析、类的层级信息,字段,名字等
-
jdk8修改JDK8 HotSpot JVM使用本地内存来存储类元数据信息,叫做元空间(Metaspace)在默认情况下Metaspace的大小只与本地内存大小有关
常用的两个参数-XX:MetaspaceSize=N 指Metaspace扩容时触发FullGC的初始值阈值,
-XX:MaxMetaspaceSize=N 指⽤于限制Metaspace增⻓的上限,防⽌因为某些情况导致 Metaspace⽆限的使⽤本地内存
-
jdk7设置永久代
-XX:PermSize
设置永久代初始大小。-XX:MaxPermSize
设置永久代最大可分配空间。 -
永久代用的jvm内存空间、元空间使用的内存
-
jmap -dump:live,format=b,file=/home/jmap/map.bin 20527
jdk9
try-with-resource
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class TryDemo {
public static void main(String[] args) throws FileNotFoundException {
//jdk7写法
String filepath = "";
OutputStream out = new FileOutputStream(filepath);
try(OutputStream temp = out;) {
temp.write((filepath+"可以学习java架构课程").getBytes());
}catch (Exception e){
e.printStackTrace();
}
//jdk9写法
OutputStream temp1 = out;
try(out;temp1) {
temp1.write((filepath+"可以学习java架构课程").getBytes());
}catch (Exception e){
e.printStackTrace();
}
}
}
只读集合
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ReadOnlyColDemo {
public static void main(String[] args) {
//jdk9之前
List<String> list = new ArrayList<>();
list.add("dfdsf");
list = Collections.unmodifiableList(list);
//jdk9之后
List<String> list1 = List.of("fdsfds","fewweew");
}
}
Stream新操作
//takeWhile:从stream流中获取一部分数据,返回从头开始尽可能多的元素,知道第一个false
List<String> list1 =List.of("springboot","java","html","","git")
.stream().takeWhile(obj->!obj.isEmpty()).collect(Collectors.toList());
System.out.println(list1);
//dropWhile:相反
List<String> list =List.of("springboot","java","html","","git")
.stream().dropWhile(obj->!obj.isEmpty()).collect(Collectors.toList());
System.out.println(list);
jdk10
var
jdk11
http
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
public class HttpDemo {
// private static final String targetUrl = "http://api.xdclass.net/pub/api/v1/web/all_category";
private static final String targetUrl = "http://47.102.106.204:8889/user-server/api/user/v1/detail";
private static final URI uri = URI.create(targetUrl);
//GET请求
private static void testGet() {
//var httpClient = HttpClient.newHttpClient();
//设置建⽴连接超时 connect timeout
var httpClient = HttpClient.newBuilder().connectTimeout(Duration.ofMillis(5000)).build();
//设置读取数据超时 read timeout
var request =
HttpRequest.newBuilder().timeout(Duration.ofMillis(3000))
.header("token", "xxx")
.header("key2", "v2")
.uri(uri).build();
try {
var response = httpClient.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body());
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
testGet();
}
}
post
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class HttpPostDemo {
private static final String targetUrl
="http://47.102.106.204:8889/product-server/api/product/v1/page";
private static final URI uri = URI.create(targetUrl);
//POST请求
private static void testPost() {
var httpClient = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder().uri(uri)
//json格式则使⽤下⾯数据
//.header("Content-Type", "application/json")
//.POST(HttpRequest.BodyPublishers.ofString("{\"phone\":\"13113777337\",\"pwd\":\"1234567890\"}"))
//form表单则使⽤下⾯配置
.header("Content-Type", "application/x-www-form-urlencoded")
.POST(HttpRequest.BodyPublishers.ofString("page=1&size=10"))
.build();
try {
var response = httpClient.send(request,
HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
testPost();
}
}
jdk13
多行文本值
var str = """
fsdfsdfdsfdsf
fdsfds
""";
switch改进
原来switch需要break才能跳出来
新版
switch(i){
case xxx->{}
case yyy->{}
default ->{}
}
java面试专题
Java虚拟机运行时数据区

- 方法区:
- 堆:
- 虚拟机栈
- 本地方法栈
- 程序计数器
集合
List
-
Vector和Arraylist、Linkedlist联系和区别?
- ArrayList:底层是数组,线程不安全,查询和修改非常快,但是增加和删除慢
- LinkedList:双向链表,查询和修改速度慢,增加和删除快
-
保证ArrayList线程安全如果做?
- 写一个包装类
- Collections.synchronizedMap();(synchronized)
- CopyOnWriteArrayList() (ReentrantLock)执行修改操作时,会先拷贝一份新的数组进行操作
-
ArrayList扩容机制
-
jdk1.7之前ArrayList默认大小是10,jdk1.7之后是0(当集合第一次添加元素时,集合大小扩容到10)
以后的扩容 = 原始大小+原始大小/2
-
个人实现ArrayList
public class MyArrayList { private static final int DEFAULT_CAPACITY=10; private static final Object[] EMPTY_ELEMENT_DATA={}; transient Object[] elementData; //实际存储大小 private int size; public MyArrayList(){ elementData = EMPTY_ELEMENT_DATA; } public MyArrayList(int initCapacity){ if(initCapacity > 0 ){ elementData = new Object[initCapacity]; }else if(initCapacity == 0){ elementData = EMPTY_ELEMENT_DATA; }else{ throw new IllegalArgumentException("参数异常"); } } public boolean add(Object e){ //判断容量 ensureCapacityInternal(size+1); elementData[size++] = e; return true; } private void ensureCapacityInternal(int minCapacity){ //首次新增元素扩容,扩容到默认容量 if(elementData == EMPTY_ELEMENT_DATA){ minCapacity = Math.max(DEFAULT_CAPACITY,minCapacity); } //判断是否需要扩容 if(minCapacity > elementData.length){ //对list进行扩容,如果默认规则计算后扩容后的容量小于最小容量,则取最小容量的值 int oldCapacity = elementData.length; int newCapacity = oldCapacity + oldCapacity>>1; if(newCapacity < minCapacity){ newCapacity = minCapacity; } Object[] objects = new Object[newCapacity]; System.arraycopy(elementData,0,objects,0,elementData.length); elementData = objects; } } /** * 通过下标获取元素 * @param index * @return */ public Object get(int index){ rangeCheck(index); return elementData[index]; } private void rangeCheck(int index){ if(index>=size || index<0){ throw new IndexOutOfBoundsException("越界"); } } /** * 判断对象所在位置 * @param o * @return */ public int indexOf(Object o){ if(o == null){ for (int i = 0 ; i < elementData.length;i++){ if(elementData[i]==null){ return i; } } }else{ for (int i = 0 ; i < elementData.length;i++){ if(elementData[i].equals(o)){ return i; } } } return -1; } public Object set(int index,Object obj){ rangeCheck(index); Object oldElement = elementData[index]; elementData[index] = obj; return oldElement; } /** * 根据索引删除元素 * @param index * @return */ public Object remove(int index){ rangeCheck(index); Object oldValue = elementData[index]; int numMoved = size - index - 1; if(numMoved > 0 ){ System.arraycopy(elementData,index+1,elementData,index,numMoved); } elementData[--size]=null; return oldValue; } public int size(){ return this.size; } }
-
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix