Java8语法和容易出现空指针异常。

java8 笔记

stream().map(),您可以将对象转换为其他对象。
Stream 有三个 match 方法,从语义上说:
allMatch:Stream 中全部元素符合传入的 predicate,返回 true;
anyMatch:Stream 中只要有一个元素符合传入的 predicate,返回 true;
noneMatch:Stream 中没有一个元素符合传入的 predicate,返回 true。
筛选filter
filter 函数接收一个 Lambda 表达式作为参数,该表达式返回 boolean,在执行过程中,流将元素逐一输送给 filter,并筛选出执行结果为 true 的元素。

collect收集过滤的结果。
去重distinct:去掉重复的结果。
截取:截取流的前N个元素。
跳过:跳过流的前n个元素。
获取任一元素findAny:findAny能够从流中随便选一个元素出来,它返回一个Optional类型的元素。
Optional介绍
Optional是Java8新加入的一个容器,这个容器只存1个或0个元素,它用于防止出现NullpointException,它提供如下方法:
常用方法:
1. Optional.of(T t) : 创建一个Optional 实例
2. Optional.empty() : 创建一个空的Optional 实例
3. Optional.ofNullable(T t):若t 不为null,创建Optional 实例,否则创建空实例
4. isPresent() : 判断容器中是否有值。
5. ifPresent(Consume lambda) :容器若不为空则执行括号中的Lambda表达式。
6. orElse(T t) : 获取容器中的元素,若容器为空则返回括号中的默认值。
7. orElseGet(Supplier s) :如果调用对象包含值,返回该值,否则返回s 获取的值
8. map(Function f): 如果有值对其处理,并返回处理后的Optional,否则返回Optional.empty()
9. flatMap(Function mapper):与map 类似,要求返回值必须是Optional
10. T get() :获取容器中的元素,若容器为空则抛出NoSuchElement异常。
获取第一个元素findFirst。
reduce函数
在流中,reduce函数能实现归约。
reduce函数接收两个参数:初始值,进行归约操作的Lambda表达式。

peek: 生成一个包含原Stream的所有元素的新Stream,同时会提供一个消费函数(Consumer实例),新Stream每个元素被消费的时候都会执行给定的消费函数;
peek

Objects.nonNull(obj):判断一个对象是否为空,if (obj != null)。

枚举类名.values(); 获得的是枚举中的实例变量。

java笔记

泛型通配符``

  1. “?”不能添加元素
    以“?”声明的集合,不能往此集合中添加元素,所以它只能作为生产者(亦即它只能被迭代),如下:
    List<?> names = Lists.newArrayList("yiifaa");
    //  通配符声明的集合,获取的元素都是Object类型
    List allNames = Lists.newArrayList("yiifee");
    allNames.addAll(names);
    //  只能以Object迭代元素
    for(Object name: names) {
        System.out.println(name);
    }
  1. “? extends T”也不能添加元素
    以“? extends T”声明的集合,不能往此集合中添加元素,所以它也只能作为生产者,如下:
    List<? extends String> names = Lists.newArrayList("yiifaa");
    //  声明消费者
    List allNames = Lists.newArrayList("yiifee");
    //  消费生产者的元素
    allNames.addAll(allNames);
  1. “? super T”能添加元素
    在通配符的表达式中,只有“? super T”能添加元素,所以它能作为消费者(消费其他通配符集合)。
    List<? super String> allNames = Lists.newArrayList("yiifaa");
    List names = Lists.newArrayList("yiifee");
    //  可以直接添加泛型元素
    allNames.addAll(names);
    //  也可以添加通配符泛型元素
    List<? extends String> names1 = Lists.newArrayList("yiifee");
    allNames.addAll(names1);
针对采用“? super T”通配符的集合,对其遍历时需要多一次转型,如下:
    //  只能获取到Object类型
    for(Object name: allNames) {
        //  这里需要一次转型
        System.out.println(name);
    }

集合初始化时,指定集合初始值大小。

HashMap 使用 HashMap(int initialCapacity) 初始化。initialCapacity = (需要存储的元素个数 / 负载因子) + 1。注意负载因子(即loader factor)默认为 0.75, 如果暂时无法确定初始值大小,请设置为 16(即默认值)。
由于没有设置容量初始大小,随着元素不断增加,容量 7 次被迫扩大, resize 需要重建 hash 表,严重影响性能。
使用 entrySet 遍历 Map 类集合 KV ,而不是 keySet 方式进行遍历。
values() 返回的是 V 值集合,是一个 list 集合对象 ;keySet() 返回的是 K 值集合,是一个 Set 集合对象 ;entrySet() 返回的是 K - V 值组合集合。

高度注意 Map 类集合 K / V 能不能存储 null 值的情况

并发处理

  • 获取单例对象需要保证线程安全,其中的方法也要保证线程安全。
  • 创建线程或线程池时请指定有意义的线程名称,方便出错时回溯。
  • 线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。
    1. 使用线程池的好处是减少在创建和销毁线程上所消耗的时间以及系统资源的开销,解决资源不足的问题。如果不使用线程池,有可能造成系统创建大量同类线程而导致消耗完内存或者“过度切换”的问题。
  • 线程池不允许使用 Executors 去创建,而是通ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
    Executors 返回的线程池对象的弊端如下:
    1. FixedThreadPool 和 SingleThreadPool :
      允许的请求队列长度为 Integer.MAX_VALUE ,可能会堆积大量的请求,从而导致 OOM 。
    2. CachedThreadPool 和 ScheduledThreadPool :
      允许的创建线程数量为 Integer.MAX_VALUE ,可能会创建大量的线程,从而导致 OOM 。
  • 高并发时,同步调用应该去考量锁的性能损耗。能用无锁数据结构,就不要用锁 ; 能锁区块,就不要锁整个方法体 ; 能用对象锁,就不要用类锁。
    说明:尽可能使加锁的代码块工作量尽可能的小,避免在锁代码块中调用 RPC 方法。
  • 并发修改同一记录时,避免更新丢失,需要加锁。要么在应用层加锁,要么在缓存加锁,要么在数据库层使用乐观锁,使用 version 作为更新依据。
    说明:如果每次访问冲突概率小于 20%,推荐使用乐观锁,否则使用悲观锁。乐观锁的重试次数不得小于 3 次。
  • 多线程并行处理定时任务时, Timer 运行多个 TimeTask 时,只要其中之一没有捕获抛出的异常,其它任务便会自动终止运行,使用 ScheduledExecutorService 则没有这个问题。
  1. String 的 matches 方法。
    匹配字符串是完全匹配。即是:str.matches(reg); str 和 reg 必须完全一致,才能匹配到,返回true,否则返回false。

  2. Java8 将 list 转成 map。
    Map<String, String> agentVoMap =
    agentVoList.stream().collect(Collectors.toMap(AgentVo::getCode, AgentVo::getName));
    AgentVo是list中存放的对象,
    AgentVo::getCode,AgentVo::getName静态调用方法。
    AgentVo::getCode:是新 map 的 key;AgentVo::getName是新 map 的 value。

  3. Java8 将一种 list 转成另一种 list。
    List collect = qrCodeLogs.stream().map(QrCodeLog::getOptCode).collect(Collectors.toList());
    qrCodeLogs: 原来的 list。
    QrCodeLog::getOptCode方法调用,如果转换后是一个对象,需要写一个转换类。
    collect(Collectors.toList()):收集为一个 list。

  4. 下表展示 Collectors 类的静态工厂方法。
    工厂方法
    返回类型
    作用
    toList
    List
    把流中所有项目收集到一个 List
    toSet
    Set
    把流中所有项目收集到一个 Set,删除重复项
    toCollection
    Collection
    把流中所有项目收集到给定的供应源创建的集合menuStream.collect(toCollection(), ArrayList::new)
    counting
    Long
    计算流中元素的个数
    sumInt
    Integer
    对流中项目的一个整数属性求和
    averagingInt
    Double
    计算流中项目 Integer 属性的平均值
    summarizingInt
    IntSummaryStatistics
    收集关于流中项目 Integer 属性的统计值,例如最大、最小、 总和与平均值
    joining
    String
    连接对流中每个项目调用 toString 方法所生成的字符串collect(joining(", "))
    maxBy
    Optional
    一个包裹了流中按照给定比较器选出的最大元素的 Optional, 或如果流为空则为 Optional.empty()
    minBy
    Optional
    一个包裹了流中按照给定比较器选出的最小元素的 Optional, 或如果流为空则为 Optional.empty()
    reducing
    归约操作产生的类型
    从一个作为累加器的初始值开始,利用 BinaryOperator 与流 中的元素逐个结合,从而将流归约为单个值累加int totalCalories = menuStream.collect(reducing(0, Dish::getCalories, Integer::sum));
    collectingAndThen
    转换函数返回的类型
    包裹另一个收集器,对其结果应用转换函数int howManyDishes = menuStream.collect(collectingAndThen(toList(), List::size))
    groupingBy
    Map<K, List>
    根据项目的一个属性的值对流中的项目作问组,并将属性值作 为结果 Map 的键
    partitioningBy
    Map<Boolean,List>
    根据对流中每个项目应用谓词的结果来对项目进行分区

  5. list 的 toString 方法
    要得到以 “,” 隔开的字符串,建议使用 google 的 Joiner类。
    list toString() 方法可能出现 空指针问题。
    List list = new ArrayList<>();
    list = null;
    System.out.println(list.size());
    当list为空时,调用list.size()/list.toString()等方法时,出现 NullPointerException;
    对于容易出现 NullPointerException ,Java8中应该使用 Optional.ofNullable(saleVolume).orElse(Lists.newArrayList()); 进行包装。负责会出现 NullPointerException 异常。
    Lists.newArrayList() 在这个 com.google.guava 包下。

com.google.guava guava 15.0
  1. map 判断是否为空。
    调用map 的 isEmpty() 方法。
    map == null:是判断是否通过 “new 进行了存储空间的分配,和键值对无关”。
    map.isEmpty(): 判断是否进行了 “键值对的put”;
    Map map = new HashMap<String ,String>(); map=null;
    System.out.println(“判断map是否为null:”+(map==null));//结果为true
    System.out.println(“判断map是否有内容:”+map.isEmpty());//NullPointerException
    对于容易出现 NullPointerException ,Java8中应该使用 Optional.ofNullable(saleVolume).orElse(Maps.newHashMap()); 进行包装。负责会出现 NullPointerException 异常。
    Maps.newHashMap() 在这个 com.google.guava 包下。
com.google.guava guava 15.0 网址:https://blog.csdn.net/meteorsshower2013/article/details/80488978?utm_source=blogxgwz0
  1. String 为空时,出现的 NullPointerException。
    当 String 被赋值为 null 时,调用 String 的所有方法时,都会报 NullPointerException 异常。
    需要用 Optional.ofNullable(str).orElse(new String()); 进行包装。避免出现 NullPointerException 异常。

  2. 把 list 转成以 “,” 隔开的字符串。

  • String.join(",", stringList): java 中 string 的原生方法。
  • Joiner.on(",").join(stringList)
    Joiner 是 com.google.guava 包下。
com.google.guava guava 15.0
  1. Optional
    Str s = new Str();
    s.setI(1);
    s.setFlag(Boolean.TRUE);
    s.setDtr(“ssss”);
    s = null;
    Optional optionalStr = Optional.ofNullable(s);
    调用get()方法时,optionalStr.get():报 Method threw ‘java.util.NoSuchElementException’ exception.

  2. 枚举
    枚举values方法,取出所有枚举值,返回值为数组。
    枚举valueOf方法,将字符串转成枚举,返回值为枚举。


版权声明:本文为qq_24143469原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。