jdk7和8新用法

olivee 5年前 ⋅ 1202 阅读

1. jdk1.7 Objects

  • 替代 obj!=null?:obj:default 运算
Objects.requireNonNullElse("value1","defaultvalue"); // 返回value1
Objects.requireNonNullElse(null,"defaultvalue"); // 返回defaultvalue
  • 判断对象空/非空
if(Objects.isNull(obj)){} // 判断对象为空
if(Objects.nonNull(obj)){} // 判断对象非空
  • 检查为空则抛出 NullPointerException 异常
Objects.requireNonNull(obj)

2. 集合API

2.1 字符串集合拼接

List<String> list = Arrays.asList("aa", "bb", "cc");
String rs1 = list.stream().map(si -> {
    return "'".concat(si).concat("'");
}).collect(Collectors.joining(",")); // 'aa','bb','cc'
String rs2 = list.stream().collect(Collectors.joining("','", "'","'")); // 'aa','bb','cc'
String rs3 = list.stream().collect(Collectors.joining(",", "'","'")); // 'aa,bb,cc'
String rs4 = String.join(",", list);// aa,bb,cc
String rs5 = new StringJoiner(",").add("aa").add("bb").add("cc").toString();// aa,bb,cc

2.2 commons-collections4: CollectionUtils

// 检查集合是否为空
CollectionUtils.isEmpty(Collection<?> coll)
// 检查集合是否为非空。
CollectionUtils.isNotEmpty(Collection<?> coll)
// 除非元素为null,否则向集合添加元素
CollectionUtils.addIgnoreNull(personList,null);
// 将两个已排序的集合a和b合并为一个已排序的列表,以便保留元素的自然顺序
CollectionUtils.collate(Iterable<? extends O> a, Iterable<? extends O> b)
// 将两个已排序的集合a和b合并到一个已排序的列表中,以便保留根据Comparator c的元素顺序。
CollectionUtils.collate(Iterable<? extends O> a, Iterable<? extends O> b, Comparator<? super O> c)
// 返回该个集合中是否含有至少有一个元素
CollectionUtils.containsAny(Collection<?> coll1, T... coll2)
// 如果参数是null,则返回不可变的空集合,否则返回参数本身。(很实用 ,最终返回List EMPTY_LIST = new EmptyList<>())
CollectionUtils.emptyIfNull(Collection<T> collection)
// 反转给定数组的顺序。
CollectionUtils.reverseArray(Object[] array);
// 差集
CollectionUtils.subtract(Iterable<? extends O> a, Iterable<? extends O> b)
// 并集
CollectionUtils.union(Iterable<? extends O> a, Iterable<? extends O> b)
//  交集
CollectionUtils.intersection(Collection a, Collection b)
// 交集的补集(析取)
CollectionUtils.disjunction(Collection a, Collection b)

2.3 guava : Lists

        // 1. 创建集合
        // guava-29.0-jre.jar
        ArrayList<String> ss1 = Lists.newArrayList("aa","bb","cc");
        // 以上代码等同于 jdk 的代码
        List<String> ss2 = Arrays.asList("aa","bb","cc");

2.4 jdk8: Stream集合的流式操作

+--------------------+       +------+   +------+   +---+   +-------+
| stream of elements +-----> |filter+-> |sorted+-> |map+-> |collect|
+--------------------+       +------+   +------+   +---+   +-------+

比如:

List<Integer> transactionsIds = 
widgets.stream()
             .filter(b -> b.getColor() == RED)
             .sorted((x,y) -> x.getWeight() - y.getWeight())
             .mapToInt(Widget::getWeight)
             .sum();

主要方法:

  • forEach 循环数据 用到Comsumer
  • map 遍历元素,并映射成一个新的集合
  • filter 过滤元素,用到 Predicate
  • limit(n) 只取前面的n个数据
  • sorted 排序
  • parallelStream 并行的流

Collectors实现了很多归约操作

  • Collectors.toList() 转换为list
  • Collectors.joining(", ") 拼接成字符串

示例:

    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 3, 2, 4);
        // 排序,并循环输出前面2个数据
        list.stream().sorted( Integer::compareTo ).limit(2).forEach(x -> System.out.println(x));
        // 过滤大于1,再取平方,再连接成字符串
        String rs = list.stream().filter(x -> x > 1).map(x -> String.valueOf(x * x)).collect(Collectors.joining(","));
        System.out.println(rs); // 输出 9,4,16
    }

3. jdk8: default 默认方法

  • 在接口中定义的默认实现,如果子类没有覆盖本方法,则默认继承该@default实现
public interface MyInterface {
    default void mydefaultMethod() {
        //...
    }
}

4. jdk8: @FunctionalInterface

  • 该注解只能标记在"有且仅有一个抽象方法"的接口上。
  • 可以有多个default方法和多个static方法
  • Supplier、Consumer、Function、Optional、Predicate等都是FunctionalInterface

4.1 Supplier

  • 可以理解为“对象生产者”,比如类的无参构造方法;无参的工厂方法
  • 生产对象的类型即为Supplier范型的类型
  • 调用Supplier对象的get方法及可触发生产对象
public class SupplierTest {
    public String attribute1 = "attribute1";
    public static String getInstance() {
        return "sdsd";
    }
    public static void main(String[] args) {
        Supplier<String> supplier = String::new; // 获取Sring的无参构造方法生产者
        System.out.println(supplier.get());
        Supplier<SupplierTest> sp = SupplierTest::new; // 获取SupplierTest的无参构造方法生产者
        System.out.println(sp.get().attribute1);
        Supplier<String> sass = SupplierTest::getInstance; // 获取SupplierTest的无参getInstance方法生产者
        System.out.println(sass.get());
    }
}

4.2 Consumer和BiConsumer

  • Consumer单个参数的方法的消费者
  • BiConsumer两个参数的方法的消费者
  • 消费的含义就是只消费不返回数据,和Function、BiFunction的区别就是 Function 有返回值

Consumer的例子

  • 顾名思义就是消费者
  • 需要消费的数据作为参数
  • 调用消费者的 accept 方法,传入“消费数据”参数,即可消费
  • 只消费,不返回数据,所以返回类型是void
public class ConsumerTest {
    static void  compute(Integer arg1) {
        System.out.println("compute " + arg1);
    }
    public static void main(String[] args) {
        // static viod 的单参数方法作为消费者
        Consumer<Integer> comsumer1 = ConsumerTest::compute;
        comsumer1.accept(123);
        // Lambda 表达式(单参数)的消费者
        Consumer<String> comsumer2 = arg1 -> System.out.println("compute " + arg1);
        comsumer2.accept("456");
        // 常用在集合中的forEach 
        List<String> list = Arrays.asList("aa","bb","cc");
        list.stream().forEach(System.out::println);
        list.stream().forEach( str -> System.out.println("str = " + str));
    }
}

BiConsumer的例子

  • 消费两个参数数据,消费数据作为参数
  • 调用消费者的 accept 方法,传入两个“消费数据”参数,即可消费
  • 只消费,不返回数据,所以返回类型是void
public class BIConsumerTest {
    void comsumeXxx(String xxx){
        System.out.println("xxx = " + xxx);
    }
    static void compute(String arg1,Integer arg2) {
        System.out.println("compute 1args1=" + arg1 + ",arg2 = " + arg2);
    }
    static void compute2(String arg1,Integer arg2) {
        System.out.println("compute2 args1=" + arg1 + ",arg2 = " + arg2);
    }
    public static void main(String[] args) {
        // static void 的双参数方法作为 BiConsumer
        BiConsumer<String,Integer> comsumer1 = BIConsumerTest::compute;
        comsumer1.accept("hello", 1);
        // 在原来的消费者后增加 comsumer, 执行的时候先执行老的, 再执行新的 comsumer
        comsumer1.andThen(BIConsumerTest::compute2).accept("hello", 1);
        // 类的 void 的单参数方法作为 BiConsumer,消费的时候参数1为对象
        BiConsumer<BIConsumerTest,String> comsumer2 =BIConsumerTest::comsumeXxx;
        comsumer2.accept(new BIConsumerTest(), "hello");
        // 用在hashmap中
        HashMap<String,Integer> map = new HashMap<String,Integer>();
        map.put("k1", 1);
        map.put("k2", 2);
        map.forEach( (k,v) -> { System.out.println("args1=" + k + ",arg2 = " + v); });
        // 或
        map.forEach(BIConsumerTest::compute);
    }
}

Consumer和BiConsumer混用的例子

public class ComsumerTest {
    private String value1;
    public static void main(String[] args) {
        ComsumerTest s = new ComsumerTest();
        s.setXxx(ComsumerTest::setValue1, "111");
        System.out.println(s.getValue1());
    }
    public void setXxx(BiConsumer<ComsumerTest,String> consumer, String value){
        // 以下两行代码等同于 consumer.accept(this, value);
        Consumer<ComsummerTest> c = istance -> consumer.accept(istance,value);
        c.accept(this);
    }
    public String getValue1() {
        return value1;
    }
    public void setValue1(String value1) {
        this.value1 = value1;
    }
}

4.3 Function和BiFunction

Function

  • 有返回值的函数调用
  • 仅有一个参数
public class FunctionTest {
    String testNoArgFunction(){
        return "no args function";
    }
    static String testFunction(Integer intArg){
        return "test_".concat(String.valueOf(intArg));
    }
    public static void main(String[] args) {
        // static 的单参数有返回值的方法作为 Function
        Function<Integer,String> f = FunctionTest::testFunction;
        // 调用 apply 有返回值
        System.out.println(f.apply(99));
        // 类的无参方法作为 Function,类对象作为函数的参数
        Function<FunctionTest,String> f2 = FunctionTest::testNoArgFunction;
        System.out.println(f2.apply(new FunctionTest()));
        // 常用在 list stream 的 map 方法 中(即传入一个值,返回一个新的值)
        Arrays.asList(11,22).stream().map( intArg -> { return "test_".concat(String.valueOf(intArg)); }).forEach(System.out::println);
        // 等同于
        Arrays.asList(11,22).stream().map( f ).forEach(System.out::println);
    }
}

BiFunction

  • 有返回值的函数调用
  • 有两个参数
public class BiFunctionTest {
    String testFunction2(Integer intArg){
        return "test2_".concat(String.valueOf(intArg));
    }
    static String testFunction(Integer intArg,Integer intArg2){
        return "test_".concat(String.valueOf(intArg)).concat(String.valueOf(intArg2));
    }
    public static void main(String[] args) {
        // static 双参数  有返回值的方法 作为 BiFunction
        BiFunction<Integer,Integer,String> bf = BiFunctionTest::testFunction;
        System.out.println(bf.apply(1, 2));
        // 等同于
        BiFunction<Integer,Integer,String> bf1 = (Integer intArg,Integer intArg2) -> {
            return "test1_".concat(String.valueOf(intArg)).concat(String.valueOf(intArg2));
        };
        System.out.println(bf1.apply(1, 2));
        // 单参参数有返回值的对象方法 作为BiFunction。相当于也是两个参数,其中第一个参数是类对象本身
        BiFunction<BiFunctionTest,Integer,String> bf2 = BiFunctionTest::testFunction2;
        System.out.println(bf2.apply(new BiFunctionTest(), 1));
    }
}

4.4 Optional

  • 基本语法
public class OptionalTest {
    public static void main(String[] args) {
        // of 方法,要求参数不能为null,如果为null,则抛出 NullPointerException 异常
        Optional<Integer> it1 = Optional.of(1);
        // ofNullable 方法,参数可以为null
        Optional<Integer> it2 = Optional.ofNullable(null);
        System.out.println("it1的值为1:" + it1.get()); // 如果值为空,则抛出NoSuchElementExceptiony异常
        System.out.println("it1值不为空:" + it1.isPresent());
        System.out.println("it2值不为空:" + it2.isPresent());
        System.out.println("it2值为空:" + !it2.isPresent());
        // 等同于
        System.out.println("it2值为空:" + (it2==Optional.<Integer>empty()));
        // 如果不是null,调用Consumer
        it1.ifPresent( value -> {
            System.out.println("it1值不为空,值=" +value);
        });
        System.out.println("it1 orElse(100)的值为it1存在的值:" + it1.orElse(100));
        System.out.println("it2 orElse(100)的值为100,因为it2的值为空:" + it2.orElse(100));
        // orElse 等同于 orElseGet,只是 orElseGet 的参数是个 Supplier 对象
        Integer rs = it1.orElseGet( () -> {
            return 100;
        });
        try {
            Integer rs2 = it2.orElseThrow();
        } catch (NoSuchElementException e) {
            System.out.println("it2值为空,抛出NoSuchElementException");
        }
        // filter(Predicate):判断Optional对象中保存的值是否满足Predicate,并返回新的Optional
        Optional<Integer> t1filter = it1.filter( intArgs -> { return intArgs>100; });
        // 由于 1>100 为false,所以t1filter的值为空
        System.out.println("t1filter值为空:" + !t1filter.isPresent());
        // map(Function):对Optional中保存的值进行函数运算,并返回新的Optional(可以是任何类型)
        Optional<String> t1map = it1.map( intArgs -> { return "hello " + intArgs; });
        System.out.println("t1map的值为:" + t1map.get());
        // flatMap():功能与map()相似, 区别是mapping函数返回必须是Optional
        Optional<String> t1map2 = it1.flatMap(intArgs -> { return Optional.<String>of("hello " + intArgs); });
        System.out.println("t1map的值为:" + t1map2.get());
    }
}
  • 用法示例
public class OptionalCase {
    static class User {
        public User() {
        }
        public User(String name) {
            this.name = name;
        }
        String name;
    }
    // 老的用法
    public static String getUserName(User u) {
        if (u == null || u.name == null) {
            return "none";
        }
        return u.name;
    }
    // 新的写法
    public static String getUserNameNew(User u) {
        return Optional.ofNullable(u)
                .map(t -> t.name)
                .orElse("none");
    }
    public static void main(String[] args) {
        System.out.println(getUserName(null)); // none
        System.out.println(getUserName(new User())); // none
        System.out.println(getUserName(new User("zhangsan"))); // zhangsan
        System.out.println(getUserNameNew(null)); // none
        System.out.println(getUserNameNew(new User())); // none
        System.out.println(getUserNameNew(new User("zhangsan"))); // zhangsan
    }
}
  • 用法实例2
public void setName(String name) throws IllegalArgumentException {
    this.name = Optional.ofNullable(name).filter(User::isNameValid)
                        .orElseThrow(()->new IllegalArgumentException("Invalid username."));
}

4.5 Predicate

  • 用于判断的FunctionalInterface
  • boolean test(T t)是它的接口函数
  • and、or表示逻辑与、逻辑或
    public static void main(String[] args) {
        // 设置一个大于100的过滤条件
        Predicate<Integer> predicate = x -> x > 100;
        // 设置一个小于200的过滤条件
        Predicate<Integer> predicate2 = x -> x < 200;
        // 设置一个偶数过滤条件
        Predicate<Integer> predicate3 = x -> x%2==0;
        System.out.println(predicate.test(101)); // 输出 true
        System.out.println(predicate.test(97)); // 输出 false
        // and 逻辑
        System.out.println(predicate.and(predicate2).test(101)); // 输出 true
        System.out.println(predicate.and(predicate2).test(201)); // 输出 fasle
        System.out.println(predicate.and(predicate2).and(predicate3).test(101)); // 输出 false
        System.out.println(predicate.and(predicate2).and(predicate3).test(102)); // 输出 true
        // or 逻辑
        System.out.println(predicate.or(predicate2).test(88)); // 输出 true
        System.out.println(predicate.or(predicate2).test(101)); // 输出 true
        // 常用在filter中
        Arrays.asList(88,101,102).stream().filter(predicate).forEach(System.out::println);// 过去大于100的并输出
    }