JDK1.8 新特性

一、Lambda表达式
lambda表达式本质上是一段匿名内部类,也可以是一段可以传递的代码
例子:筛选不同价格商品信息
1.定义商品对象

@Data
public class Product {
    private Double price;
    private String color;
}

2.定义一个MyPredicate接口

public interface MyPredicate <T> {
    boolean test(T t);
}

3.定义过滤方法及lambda

public class lambda {
    // 定义过滤方法:
    public List<Product> filterProductByPredicate(List<Product> list,MyPredicate<Product> mp){
        List<Product> prods = new ArrayList<>();
        for (Product prod : list){
            if (mp.test(prod)){
                prods.add(prod);
            }
        }
        return prods;
    }
	// 使用lambda表达式进行过滤
    @Test
    public void test4(){
        List<Product> proList = new ArrayList<>();
        Product product = new Product();
        product.setPrice((double) 7000);
        product.setColor("黑色");
        proList.add(product);
        product = new Product();
        product.setPrice((double) 9000);
        product.setColor("蓝色");
        proList.add(product);
        // 使用lambda表达式进行过滤
        List<Product> products = filterProductByPredicate(proList, (p) -> p.getPrice() < 8000);
        for (Product pro : products){
            System.out.println(pro);
        }
    }
}

当一个接口中存在多个抽象方法时,如果使用lambda表达式,并不能智能匹配对应的抽象方法,因此引入了函数式接口的概念

二、函数式接口
函数式接口的提出是为了给Lambda表达式的使用提供更好的支持。
简单来说就是只定义了一个抽象方法的接口(Object类的public方法除外),就是函数式接口,并且还提供了注解:@FunctionalInterface
常见的四大函数式接口:
1.Consumer 《T》:消费型接口,有参无返回值

@Test
    public void test(){
        changeStr("hello",(str) -> System.out.println(str));
    }

    /**
     *  Consumer<T> 消费型接口
     * @param str
     * @param con
     */
    public void changeStr(String str, Consumer<String> con){
        con.accept(str);
    }

2.Supplier 《T》:供给型接口,无参有返回值

@Test
    public void test2(){
        String value = getValue(() -> "hello");
        System.out.println(value);
    }

    /**
     *  Supplier<T> 供给型接口
     * @param sup
     * @return
     */
    public String getValue(Supplier<String> sup){
        return sup.get();
    }

3.Function 《T,R》::函数式接口,有参有返回值

@Test
    public void test3(){
        Long result = changeNum(100L, (x) -> x + 200L);
        System.out.println(result);
    }

    /**
     *  Function<T,R> 函数式接口
     * @param num
     * @param fun
     * @return
     */
    public Long changeNum(Long num, Function<Long, Long> fun){
        return fun.apply(num);
    }

4.Predicate《T》: 断言型接口,有参有返回值,返回值是boolean类型

public void test4(){
        boolean result = changeBoolean("hello", (str) -> str.length() > 5);
        System.out.println(result);
    }

    /**
     *  Predicate<T> 断言型接口
     * @param str
     * @param pre
     * @return
     */
    public boolean changeBoolean(String str, Predicate<String> pre){
        return pre.test(str);
    }

总结:函数式接口的提出是为了让我们更加方便的使用lambda表达式,不需要自己再手动创建一个函数式接口,直接拿来用就好了。
(上文中的MyPredicate可以替换成Predicate断言接口)

二、Stream API
甚至不用定义过滤方法,直接在集合上进行操作

// 使用jdk1.8中的Stream API进行集合的操作
@Test
public void test(){
    // 根据价格过滤
    proList.stream()
           .fliter((p) -> p.getPrice() <8000)
           .limit(2);
    proList.forEach(System.out::println);

    // 根据颜色过滤
    proList.stream()
           .fliter((p) -> "红色".equals(p.getColor()));
    proList.forEach(System.out::println);

    // 遍历输出商品名称
    proList.stream()
           .map(Product::getName);
    proList.forEach(System.out::println);
}

三、对hashMap等map集合的数据结构优化
在jdk1.8中对hashMap等map集合的数据结构优化。hashMap数据结构的优化
原来的hashMap采用的数据结构是哈希表(数组+链表),hashMap默认大小是16,一个0-15索引的数组,如何往里面存储元素,首先调用元素的hashcode方法,计算出哈希码值,经过哈希算法算成数组的索引值,如果对应的索引处没有元素,直接存放,如果有对象在,那么比较它们的equals方法比较内容如果内容一样,后一个value会将前一个value的值覆盖,如果不一样,在1.7的时候,后加的放在前面,形成一个链表,形成了碰撞,在某些情况下如果链表无限下去,那么效率极低,碰撞是避免不了的加载因子:0.75,数组扩容,达到总容量的75%,就进行扩容,但是无法避免碰撞的情况发生。
在1.8之后,用数组+链表+红黑树来实现hashmap,当碰撞的元素个数大于8时 & 总容量大于64,会有红黑树的引入除了添加之后,效率都比链表高。
1.8之后链表新进元素加到末尾ConcurrentHashMap (锁分段机制),concurrentLevel,jdk1.8采用CAS算法(无锁算法,不再使用锁分段),数组+链表中也引入了红黑树的使用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值