1 lambda表达式
//匿名内部类
Runnable r=new Runnable() {
@Override
public void run() {
System.out.println("hello");
}
};
//lambda表达式
Runnable a=()->{
String name=Thread.currentThread().getName();
System.out.println(name+">>hello");
};
Thread t=new Thread(a);
t.start()
//匿名内部类
Comparator<String> com= new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
// TODO Auto-generated method stub
return o2.length()-o1.length();
}
};
List list=new ArrayList();
list.add("aaa");
list.add("a");
list.add("bded");
list.add("aa");
Collections.sort(list,com);
for (Object object : list) {
System.out.println(object);
}
//lambda表达式
//⽅式1
/*Comparator<String> com=(o1,o2)->{
return o1.length()-o2.length();
};*/
//⽅式2
// Comparator<String> com=(o1, o2)->o1.length()-o2.length();
2 使⽤Stream API再优化lambda表达式
public static void main(String[] args) {
List<Employee> employees = new ArrayList<>();
employees.add(new Employee("xxx", 30, 10000));
employees.add(new Employee("yyy", 29, 8000));
employees.add(new Employee("zzz", 22, 12000));
employees.add(new Employee("张三", 21, 20000));
employees.add(new Employee("李四", 32, 22000));
// 按照年龄过滤
System.out.println("-------------按照年龄过滤--------------");
//System.out::println 是对⼀个实例⽅法的引⽤
employees.stream().filter((e)->e.getAge()>=25)
.forEach(System.out::println);
// 按照⼯资过滤
System.out.println("-------------按照⼯资过滤--------------");
employees.stream().filter((e) -> e.getSalary() >= 10000)
.forEach(e1->System.out.println(e1));
}
3 使⽤lambda表达式注意事项
Lambda引⼊了新的操作符: ->(箭头操作符),->将表达式分成两部分
左侧:(参数1,参数2…)表示参数列表;
右侧:{}内部是⽅法体
1、形参列表的数据类型会⾃动推断;
2、如果形参列表为空,只需保留();
3、如果形参只有1个,()可以省略,只需要参数的名称即可;
4、如果执⾏语句只有1句,且⽆返回值,{}可以省略,若有返回值,则若想省去{},则必须同时省略
return,且执⾏语句也保证只有1句;
5、lambda不会⽣成⼀个单独的内部类⽂件;
6、lambda表达式若访问了局部变量,则局部变量必须是final的,若是局部变量没有加final关键字,系
统会⾃动添加,此后在修改该局部变量,会报错。
Lambda表达式的语法总结: () -> ();
4 方法引用
使⽤“::”操作符将⽅法名和对象或类的名字分隔开来。以下是四种使⽤情况:
- 对象::实例⽅法
- 类::静态⽅法
- 类::实例⽅法
- 类::new
import java.util.Comparator;
import java.util.TreeSet;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Supplier;
import com.yhp.Employee;
public class Test2 {
public static void main(String[] args) {
// - 1对象::实例⽅法
//lambda表达式中的⽅法体中只调⽤了⼀个⽅法,⽽且这个⽅法的参数和
//返回值类型和lambda表达表示的抽象⽅法的参数和返回值类型相同
//Consumer中的⽅法:void accept(T t)
//Consumer<String> con=s->System.out.println(s);
//等价于
Consumer<String> con=System.out::println;
con.accept("我爱编程");
con.accept("我爱java");
List<String> names=new ArrayList<>();
names.add("xxxx");
names.add("yyyy");
names.add("zzzz");
names.add("abc");
//names.forEach(s->System.out.println(s));
names.forEach(System.out::println);
// - 2类::静态⽅法
//lambda表达式中的⽅法体中只调⽤了⼀个⽅法,⽽且这个⽅法的参数和
//返回值类型和lambda表达表示的抽象⽅法的参数和返回值类型相同
//Comparator中的⽅法: int compare(T o1, T o2);
Comparator<Integer> comparator=(o1,o2)->Integer.compare(o1, o2);
//等价于
Comparator<Integer> comparator2=Integer::compare;
TreeSet<Integer> treeSet=new TreeSet<>(comparator);
// - 3类::实例⽅法
//1 lambda表达式中的⽅法体中只调⽤了⼀个⽅法
//2 第⼀个参数作为⽅法的调⽤者,第⼆个参数作为⽅法的参数
//BiPredicate中的⽅法: boolean test(T t, U u);
BiPredicate<String, String> pre=(s1,s2)->s1.equals(s2);
//等价于
BiPredicate<String, String> pre2=String::equals;
boolean b=pre2.test("haha","haha");
System.out.println(b);
// - 4类::new
//lambda表达式的⽅法体内只有对象的创建,
//并且类型和lambda表达式表示的抽象⽅法的返回值类型相同
//Supplier中的⽅法:T get();
Supplier<Employee> sup=()->new Employee();
//等价于
//思考问题?调⽤是什么构造⽅法(⽆参构造⽅法)
Supplier<Employee> sup2=Employee::new;
Employee employee = sup2.get();
System.out.println(employee.toString());
//4.1 调⽤指定的构造⽅法 (带参构造 String int)-需要⾃定义接⼝
MySupplier<Employee> sup3=Employee::new;
Employee employee2=sup3.get("李四", 30);
System.out.println(employee2.toString());
//5数组引⽤
MyArray<String> myArray=(n)->new String[n];
//等价于
MyArray<String> myArray2=String[]::new;
String[] strings = myArray2.get(10);
System.out.println(strings.length);
}
}
public interface MyArray<T> {
T[] get(int count);
}
public interface MySupplier<T> {
T get(String name,int age); //参数列表的类型要和构造⽅法的类型相同
}
5 Stream API
Stream是Java8中处理数组、集合的抽象概念,它可以指定你希望对集合进⾏的操作,可以执⾏⾮常复杂的查找、过滤和映射数据等操作。使⽤Stream API对集合数据进⾏操作,就类似于使⽤SQL执⾏的数据库查询。也可以使⽤Stream API来并⾏执⾏操作。
简单应⽤:统计⼀个字符串类型集合中,所有⻓度⼤于3的元素个数。
//传统实现
List<String> data=new ArrayList<>();
data.add("hello");
data.add("world");
data.add("ni");
data.add("apple");
data.add("china");
int count = 0;
for (String s : data) {
if (s.length() > 3)
count++;
}
System.out.println(count);
//Stream API
long count2= data.stream().filter(s->s.length()>3).count();
System.out.println(count2);
}
上⾯代码中stream⽅法会为字符串列表⽣成⼀个Stream。filter⽅法会返回只包含字符串⻓度⼤于3的⼀个Stream,然后通过count⽅法计数。
Stream ⾃⼰不会存储元素。
Stream 不会改变源对象。相反,他们会返回⼀个持有结果的新Stream。
Stream 操作是延迟执⾏的。这意味着他们会等到需要结果的时候才执⾏。
Stream遵循“做什么,⽽不是怎么去做”的原则。只需要描述需要做什么,⽽不⽤考虑程序是怎样实现的。
6 如何使⽤Stream API
使⽤Stream,会有三个阶段(步骤):
- 创建⼀个Stream。 (创建)
- 在⼀个或多个步骤中,将初始Stream转化到另⼀个Stream的中间操作。 (中间操作)
- 使⽤⼀个终⽌操作来产⽣⼀个结果。该操作会强制他之前的延迟操作⽴即执⾏。在这之后,该Stream就不会在被使⽤了。(终⽌操作)
6.1 Stream的创建⽅法
public static void main (String[]args){
//1 Stream.of⽅法
Stream<String> stream = Stream.of("xxx", "abc", "hello", "world", "beijing");
stream.filter(s -> s.length() > 3)
.forEach(System.out::println);
//2 Arrays⼯具类
String[] country = {"中国", "美国", "韩国", "泰国"};
Stream<String> stream2 = Arrays.stream(country);
stream2.forEach(System.out::println);
//3使⽤集合的⽅法stream⽅法
//parallelStream提供了流的并⾏处理,它是Stream的另⼀重要特性,其底层使⽤Fork/Join框
架实现。简单理解就是多线程异步任务的⼀种实现。
List<String> list = new ArrayList<>();
list.add("apple");
list.add("orange");
list.add("banana");
list.add("xigua");
list.parallelStream()//并⾏操作
.filter(s -> s.startsWith("a"))
.forEach(System.out::println);
//4创建⽆限流 Stream的⽅法
//迭代
Stream<Integer> iterate = Stream.iterate(0, n -> n + 2);
iterate.limit(10).forEach(System.out::println);
//⽣成
Stream<Double> generate = Stream.generate(() -> new Random().nextDouble());
generate.limit(5).forEach(System.out::println);
}
6.2 Stream中间操作
中间操作包括:map (mapToInt, flatMap 等)、 filter、distinct、sorted、peek、limit、skip、parallel、sequential、unordered。
多个中间操作可以连接起来形成⼀个流⽔线,除⾮流⽔ 线上触发终⽌操作,否则中间操作不会执⾏任何的处理! ⽽在终⽌操作时⼀次性全部处理,称为“惰性求值”。
public static void main (String[]args){
List<Employee> employees = new ArrayList<>();
employees.add(new Employee("xxx", 30, 10000));
employees.add(new Employee("yyy", 29, 8000));
employees.add(new Employee("zzz", 22, 12000));
employees.add(new Employee("张三", 21, 20000));
employees.add(new Employee("李四", 32, 22000));
employees.add(new Employee("李四", 32, 22000));
//1.过滤 filter()
//employees.stream().filter((e)-
>e.getAge() > 25).forEach(System.out::println);
//2.限定数据 limit()- 分⻚
//employees.stream().limit(5).forEach(System.out::println);
//3.跳过 skip()
//employees.stream().skip(2).forEach(System.out::println);
//4.去重 distinct()
List list = new ArrayList();
list.add("aaa1");
list.add("aaa1");
list.add("aaa2");
//list.stream().distinct().forEach(System.out::println);
//5.映射(获取指定部分的数据,也可以对这些数据进⾏操作) -map(Function -> R
apply(T))
//employees.stream().map((e)->e.getName()).forEach(System.out::println);
//employees.stream().map((e)-
>e.getName().toUpperCase()).forEach(System.out::println);
//6.排序 sorted() 对字⺟和数字都可以排序
List list2 = new ArrayList();
list2.add(111);
list2.add(4223);
list2.add(2);
list2.add(23);
list2.add(3);
//list2.stream().sorted().forEach(System.out::println);
//⽐较对象
employees.stream().sorted((o1, o2) -> o1.getAge() -
o2.getAge()).forEach(System.out::println);
}
6.3 Stream 的终⽌操作
终⽌操作包括:forEach、forEachOrdered、toArray、reduce、collect、min、max、count、anyMatch、allMatch、noneMatch、findFirst、findAny、iterator。
遍历
forEach
查找和匹配
allMatch——检查是否匹配所有元素
anyMatch——检查是否⾄少匹配⼀个元素
noneMatch——检查是否没有匹配的元素
findFirst——返回第⼀个元素
findAny——返回当前流中的任意元素
max——返回流中最⼤值
min——返回流中最⼩值
public static void main(String[] args) {
List<Employee> employees=new ArrayList<>();
employees.add(new Employee("xxx", 30, 10000));
employees.add(new Employee("yyy", 29, 8000));
employees.add(new Employee("zzz", 22, 12000));
employees.add(new Employee("张三", 21, 20000));
employees.add(new Employee("李四", 30, 22000));
employees.add(new Employee("李四", 33, 22000));
//1.全部匹配
//boolean b=employees.stream().allMatch((e)->e.getAge()==32);
//2.⾄少匹配⼀个
//boolean b=employees.stream().anyMatch((e)->e.getAge()==32);
//3.检查都不匹配的
//boolean b=employees.stream().noneMatch((e)->e.getAge()==32);
//System.out.println(b);
//4.返回第⼀个元素
Optional<Employee> e1=employees.stream().findFirst();
System.out.println(e1.get());
//5.返回总条数
long count=employees.stream().count();
System.out.println(count);
//6.最⼤值 最⾼的⼯资
Optional<Employee> e4=employees.stream().max((e2,e3)->(int)
(e2.getSalary()-e3.getSalary()));
System.out.println(e4.get().getSalary());
//7.最⼩值
Optional<Employee> e5=employees.stream().min((e2,e3)->(int)
(e2.getSalary()-e3.getSalary()));
System.out.println(e5.get().getSalary());
//8.终⽌操作
//employees.forEach(System.out::println);
//9.归约(统计操作)-计算总的⼯资
Optional<Double> e6=
employees.stream().map(Employee::getSalary).reduce((x1,y1)->x1+y1);
System.out.println(e6.get());
//10.collect() 收集
List<String> result=
employees.stream().filter((e)-
>e.getAge()>25).map(Employee::getName).distinct().collect(Collectors.toList());
for (String string : result) {
System.out.println(string);
}
}
6.4 并⾏操作
Stream有串⾏和并⾏两种,串⾏Stream上的操作是在⼀个线程中依次完成,⽽并⾏Stream则是在多个线程上同时执⾏。
计算⼀下排序这个Stream要耗时多久:
public static void main(String[] args) {
int max = 1000000;
List<String> values = new ArrayList<>(max);
for (int i = 0; i < max; i++) {
UUID uuid = UUID.randomUUID();
values.add(uuid.toString());
}
System.out.println("----------串⾏------------");
long t0 = System.currentTimeMillis();
long count = values.stream().sorted().count();
System.out.println(count);
long t1 = System.currentTimeMillis();
long millis = t1-t0;
System.out.println(millis);
// System.out.println("-------------并⾏----------------");
// long t0 = System.currentTimeMillis();
// parallelStream()是Collection接⼝的⽅法
// long count = values.parallelStream().sorted().count();
// System.out.println(count);
// long t1 = System.currentTimeMillis();
// long millis = t1-t0;
// System.out.println(millis);
}
7 新时间⽇期API
Java 8通过发布新的Date-Time API (JSR 310)来进⼀步加强对⽇期与时间的处理。
在旧版的 Java 中,⽇期时间 API 存在诸多问题,其中有:
- ⾮线程安全 − java.util.Date 是⾮线程安全的,所有的⽇期类都是可变的,这是Java⽇期类最⼤的问题之⼀。
- 设计很差 − Java的⽇期/时间类的定义并不⼀致,在java.util和java.sql的包中都有⽇期类,此外⽤于格式化和解析的类在java.text包中定义。java.util.Date同时包含⽇期和时间,⽽java.sql.Date仅包含⽇期,将其纳⼊java.sql包并不合理。另外这两个类都有相同的名字,这本身就是⼀个⾮常糟糕的设计。
- 时区处理麻烦 − ⽇期类并不提供国际化,没有时区⽀持,因此Java引⼊了java.util.Calendar和java.util.TimeZone类,但他们同样存在上述所有的问题。
Java 8 在 java.time 包下提供了很多新的 API。以下为两个⽐较重要的 API: - Local(本地) − 简化了⽇期时间的处理,没有时区的问题。
- ZoneId (时区) − 通过定制的时区处理⽇期时间。
线程安全问题演示:
public static void main(String[] args) throws Exception{
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
Callable<Date> task = new Callable<Date>() {
@Override
public Date call() throws Exception {
return sdf.parse("20201121");
}
};
ExecutorService pool = Executors.newFixedThreadPool(10);
List<Future<Date>> results = new ArrayList<>();
for (int i = 0; i < 10; i++) {
results.add(pool.submit(task));
}
for (Future<Date> future : results) {
System.out.println(future.get());
}
pool.shutdown();
}
使⽤新时间⽇期API解决
public static void main(String[] args) throws Exception{
DateTimeFormatter formatter=DateTimeFormatter.ofPattern("yyyyMMdd");
Callable<LocalDate> task = new Callable<LocalDate>() {
@Override
public LocalDate call() throws Exception {
return LocalDate.parse("20201002", formatter);
}
};
ExecutorService pool = Executors.newFixedThreadPool(10);
List<Future<LocalDate>> results = new ArrayList<>();
for (int i = 0; i < 10; i++) {
results.add(pool.submit(task));
}
for (Future<LocalDate> future : results) {
System.out.println(future.get());
}
pool.shutdown();
}
8 本地化⽇期时间 API
LocalDate/LocalTime 和 LocalDateTime 类可以在处理时区不是必须的情况。
LocalDate、LocalTime、LocalDateTime 类的实例是不可变的对象,分别表示使⽤ ISO-8601⽇ 历系统的⽇期、时间、⽇期和时间。它们提供了简单的⽇期或时间,并不包含当前的时间信息。也不包含与时区相关的信息。
public static void main(String[] args) {
//当前时间
LocalDateTime ldt=LocalDateTime.now();
System.out.println(ldt);
//其他时间
LocalDateTime ldt2=LocalDateTime.of(2020, 10, 1, 10, 10,10);
System.out.println(ldt2);
//加时间
LocalDateTime ldt3=ldt2.plusDays(2);
System.out.println(ldt3);
//减时间
LocalDateTime ldt4 = ldt3.minusHours(2);
System.out.println(ldt4);
//获取时间部分
System.out.println(ldt.getYear());
System.out.println(ldt.getMonthValue());
System.out.println(ldt.getDayOfMonth());
System.out.println(ldt.getHour());
System.out.println(ldt.getMinute());
System.out.println(ldt.getSecond());
}
9 Instant、ZoneId
Instant 时间戳
它是以Unix元年(传统 的设定为UTC时区1970年1⽉1⽇午夜时分)开始 所经历的描述进⾏运算
ZoneId 时区
public static void main(String[] args) throws Exception {
//时间戳
Instant instant=Instant.now();
System.out.println(instant);
Thread.sleep(1000);
Instant instant2=Instant.now();
long millis = Duration.between(instant, instant2).toMillis();
System.out.println(millis);
//时区
System.out.println(ZoneId.getAvailableZoneIds());
ZoneId zone1 = ZoneId.of("Europe/Berlin");
ZoneId zone2 = ZoneId.of("Brazil/East");
System.out.println(zone1.getRules());
System.out.println(zone2.getRules());
}
10 时间矫正器 TemporalAdjuster
TemporalAdjuster : 时间校正器。有时我们可能需要获 取例如:将⽇期调整到“下个周⽇”等操作。
TemporalAdjusters : 该类通过静态⽅法提供了⼤量的常 ⽤ TemporalAdjuster 的实现。
例如获取下个周⽇
LocalDate date=LocalDate.now();
//下周5
System.out.println(date.with(TemporalAdjusters.next(DayOfWeek.FRIDAY)));
//下周2
System.out.println(date.with(TemporalAdjusters.next(DayOfWeek.TUESDAY)));
//下周⽇(周⽇为每周的第⼀天)
System.out.println(date.with(TemporalAdjusters.next(DayOfWeek.SUNDAY)));
11 DateTimeFormatter
java.time.format.DateTimeFormatter 类:该类提供了三种 格式化⽅法:
预定义的标准格式
语⾔环境相关的格式
⾃定义的格式
public static void main(String[] args) throws InterruptedException,
ExecutionException {
//获得时间
LocalDate date=LocalDate.now();
System.out.println(date);
LocalTime time=LocalTime.now();
System.out.println(time);
LocalDateTime datetime=LocalDateTime.now();
System.out.println(datetime);
//格式化
DateTimeFormatter format=DateTimeFormatter.ofPattern("yyyy年MM⽉dd⽇
HH:mm:ss E");
//Date->String
String str=format.format(datetime);
System.out.println(str);
//String->Date
String date2="2019年08⽉22⽇ 14:01:46 星期四";
LocalDateTime da=LocalDateTime.parse(date2,format);
System.out.println(da);
}
12 接⼝中的默认⽅法和静态⽅法
在接⼝中可以使⽤default和static关键字来修饰接⼝中定义的普通⽅法
public interface Interface {
default String getName(){
return "zhangsan";
}
static String getName2(){
return "zhangsan";
}
}
在JDK1.8中很多接⼝会新增⽅法,为了保证1.8向下兼容,1.7版本中的接⼝实现类不⽤每个都重新实现新添加的接⼝⽅法,引⼊了default默认实现,static的⽤法是直接⽤接⼝名去调⽅法即可。当⼀个类继承⽗类⼜实现接⼝时,若后两者⽅法名相同,则优先继承⽗类中的同名⽅法,即“类优先”,如果实现两个同名⽅法的接⼝,则要求实现类必须⼿动声明默认实现哪个接⼝中的⽅法。
13 对HashMap的优化
在jdk1.8中对hashMap等map集合的数据结构优化。hashMap数据结构的优化 。原来的hashMap采⽤的数据结构是哈希表(数组+链表),hashMap默认⼤⼩是16,⼀个0-15索引的数组,如何往⾥⾯存储元素,⾸先调⽤元素的hashcode ⽅法,计算出哈希码值,经过哈希算法算成数组的索引值,如果对应的索引处没有元素,直接存放,如果有对象在,那么⽐较它们的equals⽅法⽐较内容 如果内容⼀样,后⼀个value会将前⼀个value的值覆盖,如果不⼀样,在1.7的时候,后加的放在前⾯,形成⼀个链表,形成了碰撞,在某些情况下如果链表⽆限下去,那么效率极低,碰撞是避免不了的
加载因⼦:0.75,数组扩容,达到总容量的75%,就进⾏扩容,但是⽆法避免碰撞的情况发⽣在1.8之后,在数组+链表+红⿊树来实现hashmap,当碰撞的元素个数⼤于8时 & 总容量⼤于64,会有红⿊树的引⼊ 。除了添加之后,效率都⽐链表⾼。JDK1.7及之前的 ConcurrentHashMap 使⽤ 锁分段
机制 实现,JDK1.8则使⽤ 数组+链表+红⿊树数据结构 和 CAS原⼦操作实现。
jdk 7 与 jdk 8 中关于HashMap的对⽐
8时红⿊树+链表+数组的形式,当桶内元素⼤于8时,便会树化
hash值的计算⽅式不同
1.7 table在创建hashmap时分配空间,⽽1.8在put的时候分配,如果table为空,则为table分配空间。
在发⽣冲突,插⼊链中时,7是头插法,8是尾插法。
在resize操作中,7需要重新进⾏index的计算,⽽8不需要,通过判断相应的位是0还是1,要么依旧是原index,要么是oldCap + 原index
14 Optional 类
Optional 类是⼀个可以为null的容器对象。如果值存在则isPresent()⽅法会返回true,调⽤get()⽅法会返回该对象。
Optional 是个容器:它可以保存类型T的值,或者仅仅保存null。Optional提供很多有⽤的⽅法,这样我们就不⽤显式进⾏空值检测。
Optional 类的引⼊很好的解决空指针异常。
类中的⽅法
注意: 这些⽅法是从 java.lang.Object 类继承来的。
示例:
import java.util.Optional;
public class Test {
public static void main(String args[]){
Test test = new Test();
Integer value1 = null;
Integer value2 = new Integer(10);
// Optional.ofNullable - 允许传递为 null 参数
Optional<Integer> a = Optional.ofNullable(value1);
// Optional.of - 如果传递的参数是 null,抛出异常 NullPointerException
Optional<Integer> b = Optional.of(value2);
System.out.println(test.sum(a,b));
}
public Integer sum(Optional<Integer> a, Optional<Integer> b){
// Optional.isPresent - 判断值是否存在
System.out.println("第⼀个参数值存在: " + a.isPresent());
System.out.println("第⼆个参数值存在: " + b.isPresent());
// Optional.orElse - 如果值存在,返回它,否则返回默认值
Integer value1 = a.orElse(new Integer(0));
//Optional.get - 获取值,值需要存在
Integer value2 = b.get();
return value1 + value2;
}
}
运⾏结果:
第⼀个参数值存在: false
第⼆个参数值存在: true
10
15 Base64
在Java 8中,Base64编码已经成为Java类库的标准。
Java 8 内置了 Base64 编码的编码器和解码器。
Base64⼯具类提供了⼀套静态⽅法获取下⾯三种BASE64编解码器
基本:输出被映射到⼀组字符A-Za-z0-9+/,编码不添加任何⾏标,输出的解码仅⽀持A-Za-z0-9+/。
URL:输出映射到⼀组字符A-Za-z0-9+_,输出是URL和⽂件。
MIME:输出隐射到MIME友好格式。输出每⾏不超过76字符,并且使⽤’\r’并跟随’\n’作为分割。编码输出最后没有⾏分割。
内嵌类
⽅法
注意:Base64 类的很多⽅法从 java.lang.Object 类继承。
示例:
import java.util.Base64;
import java.util.UUID;
import java.io.UnsupportedEncodingException;
public class Test {
public static void main(String args[]){
try {
// 使⽤基本编码
String base64encodedString =
Base64.getEncoder().encodeToString("yhp".getBytes("utf-8"));
System.out.println("Base64 编码字符串 (基本) :" + base64encodedString);
// 解码
byte[] base64decodedBytes =
Base64.getDecoder().decode(base64encodedString);
System.out.println("原始字符串: " + new String(base64decodedBytes, "utf-
8"));
//url编码
base64encodedString =
Base64.getUrlEncoder().encodeToString("http://www.baidu.com".getBytes("utf-
8"));
System.out.println("Base64 编码字符串 (URL) :" + base64encodedString);
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < 10; ++i) {
stringBuilder.append(UUID.randomUUID().toString());
}
//Mime编码
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());
}
}
}