Java8新特性

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,会有三个阶段(步骤):

  1. 创建⼀个Stream。 (创建)
  2. 在⼀个或多个步骤中,将初始Stream转化到另⼀个Stream的中间操作。 (中间操作)
  3. 使⽤⼀个终⽌操作来产⽣⼀个结果。该操作会强制他之前的延迟操作⽴即执⾏。在这之后,该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());
                }
            }
        }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

凌晨里的无聊人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值