JAVA 8-13 高级特性

二 JDK8新特性之接口和日期处理

1 default关键字

-- 1.8以前接口只能有抽象方法,不能有任何方法实现
-- default修饰方法,可以定义具体的方法实现
-- 实现类可以直接调用

2 Base64

public static void oldBase64() throws IOException {
    BASE64Encoder encoder = new BASE64Encoder();
    String encodesString = encoder.encode("3322".getBytes());

    BASE64Decoder decoder = new BASE64Decoder();
    String decodesString = new String(decoder.decodeBuffer(encodesString));

    System.out.println(encodesString + " -------- " + decodesString);
}

public static void newBase64(){
    Base64.Encoder encoder = Base64.getEncoder();
    String encodesString = encoder.encodeToString("234234".getBytes());

    Base64.Decoder decoder = Base64.getDecoder();
    String decodesString = new String(decoder.decode(encodesString));

    System.out.println(encodesString + " -------- " + decodesString);
}

3 时间日期处理

1 时间处理API 
	-- SimpleDateFormat,Calendar等缺点:
		java.util.Date 非线程安全
		日期/时间对象比较、加减比较麻烦
			
	-- 新版提供Date-Time API(JSR 310)
		
		包:java.time
		核心类:
			LocalDate(不包含具体时间的日期)
			LocalTime	不含日期的时间
			LocalDateTime 包含日期和时间

2 时间日期格式化
	
	-- 引入线程安全的DateTimeFormatter
	-- 日期差 Duration

4 Optional

-- 解决空指针异常
	
	本质是一个有可选值得包装类 
	
-- 创建Optional类

	ofNullable()
	get()		调用前判断是否有值
	isPresent() 值存在则isPresent返回true
		Optional<Dog> optional1Not = Optional.ofNullable(dog);
		System.out.println(optional1Not.isPresent());
		 
	orElse()	如果有值返回,否则返回参数值
		Dog dog2 = new Dog(44);
		dog = Optional.ofNullable(dog).orElse(dog2);
		System.out.println(dog.getAge());

		Dog dog3 = null;
		int result = Optional.ofNullable(dog3).map(obj -> obj.getAge()).orElse(7);
		System.out.println(result);

三 JDK8 Lambda表达式

1 lambda表达式
–函数式编程
将函数(行为)作为一个参数进行传递。面向对象编程 是对数据的抽象,函数式编程则是对行为的抽象

--创建线程

	jdk8之前
		new Thread(new Runnable() {
        @Override
        public void run() {
            System.out.println("old thread create");
        }
		}).start();
	jdk8之后
		new Thread(()->System.out.println("new Thread create")).start();
		
--集合容器

	使用前
		List<String> list = Arrays.asList("111","000","aaa");
		Collections.sort(list, new Comparator<String>() {
			@Override
			public int compare(String o1, String o2) {
				return o2.compareTo(o1);
			}
		});
		for(String s : list){
			System.out.println(s);
		}
	使用后
		List<String> list = Arrays.asList("111","000","aaa");
		Collections.sort(list,(a,b)->b.compareTo(a));
		for(String s : list){
			System.out.println(s);
		}
		
--使用场景
	一个接口中只包含一个方法,语法:(params)->expression

	参数列表:
		括号中参数列表的数据类型可省略
		括号中的参数只有一个,参数类型和()都可以省了
	方法体:
		如果{}中的代码只有1行,无论有无返回值,可省略{},return,分号要一起省略

--好处:Lambda表达式的实现方式本质是以匿名内部类的方式进行实现

	重构有臃肿代码,更高效的开发效率,尤其集合Collection操作的时候

2 自定义Lambda接口编程

-- 自定义Lambda接口编程	
	定义一个函数式接口,@FunctionalInterface
	编写一个方法,输入需要的数据和接口
	在调用方法时传入数据和lambda表达式
	
	
	@FunctionalInterface
	public interface OperFunc<R,T> {
		R operator(T t1,T t2);
	}
	public static Integer operator(Integer t1,Integer t2,OperFunc<Integer,Integer> of){
	   return of.operator(t1,t2);
	}
	public static void testOper(){
		System.out.println(operator(2,3,(Integer x,Integer y)-> {
			return x+y;
		}));
		System.out.println(operator(33,2,(x,y)->x+y));
		System.out.println(operator(42,23,(x,y)->x-y));
	}

四 函数式编程Function

1 Function接口的使用
Lambda表达式必须先定义接口,创建后才可以用;JDK内置了许多接口

JAVA8 内置的四大核心函数式接口

Consumer:消费型接口:有入参,无返回
void accept(T t);

Supplier:共给型接口:无入参,有返回
T get();

Function<T,R>:函数型
R apply(T t);

Predicate:断言型接口,有入参,有返回
boolean testOper(T t);

– 例子

  public class FunctionUtils implements Function {
    @Override
    public Object apply(Object o) {
        return o+"apply ....";
    }


    public static void testFunc(){
        Function functionUtils = new FunctionUtils();
        functionUtils.apply("op---");

        //常规使用
        Function<Integer,Integer> function = p->p*10;
        System.out.println(function.apply(11));
    }
}

2 BitFunction接口
BitFunction<T,U,R> 接收2个参数

BiFunction<Integer,Integer,Integer> function = (x,y)->x+y;
System.out.println(function.apply(20,33));

3 Consumer接口
无输入,无返回,常用于打印和发短信

public static void testConsumer(){
    Consumer<String> consumer = phone ->{
        System.out.println("手机" +phone+"已发送");
    };
    sendMsg("111111111",consumer);
    
    //集合应用
    List<String> list = Arrays.asList("sdf","ddd");
    list.forEach(str->{
        System.out.println(str);
    });
}
public static void sendMsg(String phone, Consumer<String> consumer){
    consumer.accept(phone);
}

4 Supplier接口
无入参,有返回,常用于:无参的工厂方法

public static void testSupplier(){
    Dog dog = newDog();
    System.out.println(dog.getAge());
}
public static Dog newDog(){
   Supplier<Dog> supplier = ()->{
       Dog dog=new Dog();
       dog.setAge(2);
       return dog;
   };
   return supplier.get();
}

5 Predicate接口
接收参数,用于判断是否满足一定的条件,过滤数据


   public static void testPredicate(){
        List<String> list = Arrays.asList("322","abc","jone","jane");
        list = filter(list, str -> str.startsWith("a") );
        System.out.println(list.toString());
    }
    public static List<String>filter(List<String> list , Predicate<String>predicate){
        List<String> result = Lists.newArrayList();
        list.forEach(str->{
            if(predicate.test(str)){
                result.add(str);
            }
        });
        return result;
    }
	

6 方法引用与构造函数引用

方法引用是一种更简洁易懂的Lambda表达式,操作符 :: ,用来直接类或者实例已经存在的方法或者构造方法

静态方法, ClassName::methodName
实例方法,Instance::methodName
构造函数, 类名::new

   public static void test1(){
		// 静态函数引用
		Function<String,Integer> function = Integer::parseInt;
		Integer t1 = function.apply("22");
		System.out.println(t1);

		//非构造函数引用
		String content = "JAVA";
		Function<Integer,String> subFun = content::substring;
		System.out.println(subFun.apply(1));

		//多个参数构造函数引用
		BiFunction<String,Integer, User> biFunction = User::new;
		User u1 = biFunction.apply("jone",11);
		System.out.println(u1.getAge());

		//函数引用
		sayHi(String::toUpperCase,"abcd");

    }
    public static void sayHi(Function<String,String> function,String msg){
        System.out.println(function.apply(msg));
    }
   

五 流Stream

1 stream使用
– 将集合转换为一种叫做"流"的元素队列,通过声明性方式能够对集合中的
每个元素进行一系列并行或者串行的流水线操作
– 元素是特定类型的对象,元素集合看成流。流在管道中传输,且可以在管道的节点上进行处理,比如:排序,聚合,过滤等
– 操作;
数据元素:List、Set、Map等
生成流,串行流stream()并行流parallelStream()
中间操作,排序,聚合,转换等
终端操作,很多流操作本身就会返回一个流,多个操作可以直接连接起来,最后统一进行收集
– 例子

		public static void test1(){
			List<String> list = Arrays.asList("111","333","4343");
			List<String> result = list.stream().map(str->"add"+str).collect(Collectors.toList());
			result.forEach(str->{
				System.out.println(str);
			});
		}
		

2 map函数和filter函数

– map
将流中的每个元素T映射为R
场景:转换对象

	List<User> users = Arrays.asList(new User("JONE",22),new User("jane",33));
	List<UserDO> results = users.stream().map(obj -> {
		UserDO userDO = new UserDO(obj.getName(),obj.getAge());
		return userDO;
	}).collect(Collectors.toList());
	results.forEach(obj ->{
		System.out.println(obj.getAge());
	});
	

– filter
场景:过滤条件

	public static void filterTest(){
        List<String> list = Arrays.asList("dsf","sfddsssss","2342342343");
        list = list.stream().filter(str -> str.length()>5).collect(Collectors.toList());
        System.out.println(list);
    }
  
	

3 sorted函数和limit函数

– sorted

	List<String>result1 = list.stream().sorted().collect(Collectors.toList());
	//按长度排序
	List<String> result2 = list.stream().sorted(Comparator.comparing(obj->obj.length())).collect(Collectors.toList());
	//按长度反序
	List<String> result3 = list.stream().sorted(Comparator.comparing(obj->obj.length(),Comparator.reverseOrder())).collect(Collectors.toList());

	List<String> result4 = list.stream().sorted(Comparator.comparing(String::length).reversed()).collect(Collectors.toList());
	

– limit

	//排序后取前3数据
	List<String> result5 = list.stream().sorted(Comparator.comparing(String::length).reversed()).limit(3).collect(Collectors.toList());
	

4 match函数

//数组中字符串是否都全部长度》5
boolean flag = list.stream().allMatch(obj -> obj.length()>5);
//数组中字符串是否存在长度》8
flag = list.stream().anyMatch(obj -> obj.length() >8);

5 min和max

//返回长度最长的字符串
String s1 = list.stream().max(Comparator.comparingInt(obj ->obj.length())).get();

//返回年龄最小的用户
List<User> users = Arrays.asList(new User("JONE",22),new User("jane",33));
User user = users.stream().min(Comparator.comparingInt(User::getAge)).get();

六 JDK8并行流parallelStream

1 parallelStream
–为什么用
集合做重复操作,如果使用串行会相当耗时,一般采用多线程来加快
parallelStream用fork/join框架提供了并发执行能力

–底层原理
线程池(ForkjoinPool)维护一个线程队列
分割任务,将父任务分成子任务,完全贴合分治思想

–区别

parallelStream输出已排序的数组时,会乱序

–parallelStream是否一定比stream串行快
错误、数量少的情况,可能串行更快,Forkjoin会更耗性能
–多数情况并行比串行快,是否都可以用并行
不行,部分情况有线程安全问题,parallelStream里面使用的外部变量;
如:多个线程往list里加数据,可以使用CopyOnWriteArrayList线程安全的集合

	for(int i=0;i<10;i++) {
		List list = new ArrayList();
		//List list = new CopyOnWriteArrayList();
		IntStream.range(0, 100).parallel().forEach(list::add);
		System.out.println(list.size());
	}
	

2 reduce操作

-- 聚合操作
-- 根据一定规则将stream中的元素进行计算后返回唯一的值
-- 常用方法
		-- Optional<T> reduce(BinaryOperator<T> accumulator);
		//accumulator累加计数器
		//累加
        int value = Stream.of(0,1,4,32,454).reduce((obj1,obj2)->obj1+obj2).get();
        System.out.println(value);
        value = Stream.of(0,1,4,32,454).reduce(new BinaryOperator<Integer>() {
            @Override
            public Integer apply(Integer integer, Integer integer2) {
                return integer+integer2;
            }
        }).get();
		//identity初始值
		-- T reduce(T identity,BinaryOperator<T> accumulator)
		value = Stream.of(0,1,4,32,454).reduce(100,(sum,item)->sum+item);
		//求最大值
		value = Stream.of(1645, 234345, 32,
                44434,564534,435,34343542,212).max(Comparator.comparingInt(Integer::shortValue)).get();
        System.out.println(value);
        value = Stream.of(1645, 234345, 32,
                44434,564534,435,34343542,212).reduce((o1,o2) -> o1>o2?o1:o2).get();
			

3 forEach
– 不能修改包含本地变量的值
– 不能用break或者return或者continue等关键字结束

七 jdk8收集器和集合统计

1 collect收集器
– 方法作用
对流中的数据进行归集操作
有两个重载方法,在Stream接口
R collect(Supplier supplier,BiConsumer<R,? super T>accumulator,BiConsumer<R,R> combiner);
<R,A> collect(Collector<? super T,A,R> collector);
– Collector作用
提供很多工厂方法
– Collectors
工具类,提供常见的收集器实现
– 例子

		List<String> list = Arrays.asList("sdfsf","dd","234234");
        List<String> list1 = list.stream().collect(Collectors.toList());
        Map<String,String> map = list.stream().collect(Collectors.toMap(obj ->obj,obj->obj));
        LinkedList<String> list2 = list.stream().collect(Collectors.toCollection(LinkedList::new));
        Set<String> set = list.stream().collect(Collectors.toCollection(TreeSet::new));
		

2 collectors.join 拼接
– join实现

	public static Collector<CharSequence, ?, String> joining() {
		 return new CollectorImpl<CharSequence, StringBuilder, String>(
		 StringBuilder::new, StringBuilder::append,
		 (r1, r2) -> { r1.append(r2); return r1; },
		 StringBuilder::toString, CH_NOID);
	}

	-- 例子
		List<String> list = Arrays.asList("sdfsf","dd","234234");
        String ss = Stream.of("sdfsf","dd","234234").collect(Collectors.joining());
        String ss2 = list.stream().collect(Collectors.joining(";"));
        //连接符,前缀,后缀
        String ss3 = list.stream().collect(Collectors.joining(",","[","]"));
		

3 partitioningBy 分组

	-- Collectors.partitioningBy
		public static <T> Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super
			T> predicate) {
			return partitioningBy(predicate, toList());
		}
		
	-- 对list分组,字符串长度大于4,其他为另一组
		List<String> list = Arrays.asList("java", "springboot",
                "HTML5","nodejs","CSS3");
        Map<Boolean,List<String>> map = list.stream().collect(Collectors.partitioningBy(obj -> obj.length()>4));
		System.out.println(map);
		{false=[java, CSS3], true=[springboot, HTML5, nodejs]}
		

4 group by 分组

	-- Collections.groupingBy
		public static <T, K> Collector<T, ?, Map<K, List<T>>>
			groupingBy(Function<? super T, ? extends K> classifier) {
			return groupingBy(classifier, toList());
		}
		
	-- 根据学生所在省份,进行分组
		List<User> users = Arrays.asList(new User("⼴东", 23), new
                User("⼴东", 24), new User("⼴东", 23),new User("北京", 22), new
                User("北京", 20), new User("北京", 20),new User("海南", 25));
        Map<String,List<User>> map = users.stream().collect(Collectors.groupingBy(User::getName));
		
5 分组统计
	-- 聚合函数进行统计查询,分组后统计个数
	-- Collectors.counting()
	
	-- 统计各个省份的人数
		Map<String,Long> map2 = users.stream().collect(Collectors.groupingBy(User::getName,Collectors.counting()));

6 统计相关

	-- summarizing
		public static <T>Collector<T, ?, DoubleSummaryStatistics> summarizingDouble(ToDoubleFunction<? super T> mapper) {
			return new CollectorImpl<T, DoubleSummaryStatistics, DoubleSummaryStatistics>(
					DoubleSummaryStatistics::new,
					(r, t) -> r.accept(mapper.applyAsDouble(t)),
					(l, r) -> { l.combine(r); return l; }, CH_ID);
		}
		
	-- 统计学生的各个年龄信息
	
		IntSummaryStatistics intSummaryStatistics = users.stream().collect(Collectors.summarizingInt(User::getAge));
		System.out.println("max ="+intSummaryStatistics.getMax());
        System.out.println("avg ="+intSummaryStatistics.getAverage());
        System.out.println("count="+intSummaryStatistics.getCount());
	

八 Collection实战

1 需求描述:电商订单数据处理,根据下面的list1和list2各10个订单
– 统计出同时被两个人购买的商品列表(交集)
– 统计出两个人购买商品的差集
– 统计出全部被购商品的去重并集
– 统计两个人的分别购买订单的平均价格
– 统计两个人的分别购买订单的总价格

//统计出同时被两个人购买的商品列表
//重写equals方法和hashCode方法
List<VideoOrder> list = videoOrders1.stream().
		filter(videoOrders2::contains).collect(Collectors.toList());
list.forEach(obj -> System.out.println(obj.getVideoTitle()));


//统计出两个人购买商品的差集
List<VideoOrder> list1 = videoOrders1.stream().filter(obj ->!videoOrders2.contains(obj)).collect(Collectors.toList());
List<VideoOrder> list2 = videoOrders2.stream().filter(obj ->!videoOrders1.contains(obj)).collect(Collectors.toList());
System.out.println(list1.toString());
System.out.println(list2.toString());

//统计出全部被购商品的去重并集
List<VideoOrder> all = videoOrders1.parallelStream().collect(Collectors.toList());
all.addAll(videoOrders2);
//必须重写equals和hashCode
List<VideoOrder> allDistinct = all.stream().distinct().collect(Collectors.toList());
allDistinct.forEach(obj ->
		System.out.println(obj.getVideoTitle()));

//统计两个人的分别购买订单的平均价格
IntSummaryStatistics intSummaryStatistics1 = videoOrders1.stream().collect(Collectors.summarizingInt(VideoOrder::getTotalFee));
System.out.println(intSummaryStatistics1.getAverage());

Double d2 = videoOrders2.stream().collect(Collectors.averagingDouble(VideoOrder::getTotalFee));
System.out.println(d2);

//统计两个人的分别购买订单的总价格
System.out.println(intSummaryStatistics1.getSum());
int sum2 = videoOrders2.stream().collect(Collectors.summingInt(VideoOrder::getTotalFee));
System.out.println(sum2);

九 JDK8新的内存空间和异常处理

1 新内存空间Matespace

--JVM内存知识
	
  ## 永久代(permanent) ,通过命令行设置参数--XX:MaxPermSize来设置永久代最大可分配内存空间
  ## JDK8设置PermSize和MaxPermSize会被忽略
  ## 永久代作用:存放class和mate信息,当class被加载loader时会被存储到该区域,如方法的编译信息
  及字节码、常量池和符号解析、类的层级信息、字段、名字等
  ## java.lang.OutOfMemoryError:PermGen space,原因:永久代空间不够,类太多导致
  
-- jdk8的修改
  jdk8修改HotSpot JVM使用本地内存来存储元数据信息,即 元空间
  常用参数:-XX:MetaspaceSize=N 扩容时触发FullGC的初始化阈值
			-XX:MaxMetaspaceSize=N 限制Metaspace增长的上线,防止因为某些情况导致其无限的使用本地内存
			
  查看大小:
	jstat -gc pid MC:current metaspace capacity MU:metaspace utilization 单位:KB

2 JDK7特性try-with-resources

	-- try-with-resources
	
	public static void testNewTry(){
        try(OutputStream out = new FileOutputStream(filePath)){
            out.write("abcsss".getBytes());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void testOldTry() throws FileNotFoundException {

        OutputStream out = new FileOutputStream(filePath);
        try{
            out.write("abc".getBytes());
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try{
                out.close();
            }catch (IOException e){
                e.printStackTrace();
            }
        }
    }
	
	## 实现AutoCloseable接口的类,在try()里声明该类实例的时候,try结束自动调用close方法,会早于finally调用的方法
	## 不管是否出现异常,try()里的实例都会被调用close
	## try里面可以声明多个自动关闭的对象、越早声明的对象、会越晚被close

十 JDK9的常用特性

1 JDK9私有方法
– JDK8新增静态方法和默认方法,不支持私有方法
– JDK9新增私有方法

public interface OrderPay {
	void pay();

	default void defaultPay(){
		privateMethod();
	}

	private void privateMethod(){
		System.out.println("私有方法");
	}
}

-- 注意点
	## 接口中的静态方法不能被实现类继承和子接口继承,但是接口中的非静态的默认方法可以被实现类继承
	如:List.of(),但是ArrayList不能继承
	## 类的静态方法可以被继承

2 JDK9的增强try-with-resources

public static void testNewJdk9Try() throws FileNotFoundException {
    OutputStream out = new FileOutputStream(filePath);
    try(out){
        out.write("dsds".getBytes());
    }catch (IOException e){
        e.printStackTrace();
    }
}
-- JDK9中,在try外进行初始化,括号内引用,既可以实现资源自动关闭,多个变量则分号分隔

十一 Stream和集合API

1 只读集合
– jdk9前
public static void testBeforeJdk9(){
List list = Arrays.asList(“sfdsdf”,“323”,“sdf”);
//只读,不可修改
list = Collections.unmodifiableList(list);

    Map map = new HashMap<String,String>();
    map.put("age","18");
    map.put("name","join");
    map = Collections.unmodifiableMap(map);
}

-- jdk9后
public static void testAfterJdk9(){
    List<String> list = List.of("sfdsdf","323","sdf");
    Map map = Map.of("age","18","name","join");
	Set set = Set.of("1323","423","234");
}

2 JDK9新增的Stream API

-- takeWhile
 有序集合:从Stream中获取一部分数据,返回从头开始的尽可能多的元素,直到遇到第一个false结果,如果第一个值不满足断言条件,将返回一个空的Stream
 List<String> list = List.of("git","html","","dd").stream()
            .takeWhile(obj ->!obj.isEmpty()).collect(Collectors.toList());


-- dropWhile
 与takeWhile相反,返回剩余元素
 
 list = List.of("git","html","","dd").stream()
            .dropWhile(obj ->!obj.isEmpty()).collect(Collectors.toList());

十二 JDK10和JDK11常见特性

1 JDK10之局部变量类型var

-- Local-Variable Type Inference(局部变量类型推断)
	仅适用于局部变量
	不能使用于方法形参、构造函数形参、方法返回类型或任何其他类型的变量声明
	标识符var不是关键字,而是一个保留类型名称,而且不支持类或接口

2 JDK11新增Http客户端
JDK9引入在JDK10更新
– 常用类和接口

		HttpClient.Builder  构建工具类
		HttpRequest.Builder 
		HttpRequest.BodyPublisher	
			将java对象转换为可发送的HTTP body字节流,如form表单提交
			
		HttpResponse.BodyHandler
			处理收到的Response Body
			

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

rong742954

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

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

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

打赏作者

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

抵扣说明:

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

余额充值