GreenTeaJUG 活动 第25期 杭州

时间:2017-01-21 14:00-17:00
地点:杭州华星路互联网大厦17楼 “冶金炉”会议室,挖财(创业大厦对面)
组织:@JianhaoMo ,@hongjiang_wang
志愿者:郁磊,吴璞渊,朱婉怡

时间:2017-01-21 14:00-17:00
主题:JDK 9: Big Changes to Make Java Smaller
摘要:
JDK 9 is scheduled for general availability in July 2017.  The biggest new feature for this release of Java is Project Jigsaw that brings modularity to both the core JDK libraries as well as, potentially, application code.

Modularizing the JDK core libraries is not just a simple matter of breaking up the rt.jar file into a number of sections.  The Jigsaw module system allows for encapsulation of packages that developers do not want publicly exposed. Encapsulation of JDK internal APIs will potentially break backwards compatibility for application code that uses these APIs.  This session will explain the practicalities of running applications on JDK 9.

We’ll also look at how you can migrate existing applications to the new module system in a gradual and controlled way to minimize impact on users.

讲师:Simon Ritter, Azul System 布道师,2014年曾作为Oracle布道师在中国巡回演讲,宣讲Java8。

Simon has been in the IT business since 1984 and holds a Bachelor of Science degree in Physics from Brunel University in the U.K. Originally working in the area of UNIX development for AT&T UNIX System Labs and then Novell, Simon moved to Sun in 1996. At this time he started working with Java technology and has spent time working both in Java development and consultancy. Having moved to Oracle as part of the Sun acquisition he now focuses on the core Java platform, Java for client applications and embedded Java. He also continues to develop demonstrations that push the boundaries of Java for applications like gestural interfaces, embedded robot controllers and in-car systems.Follow him on Twitter, @speakjava.
报名

活动报名请按照如下格式发邮件到event@greenteajug.cn
主题:GreenTeaJUG活动 第25期 杭州
姓名:XXX
手机号码:xxxxxxxxxxx
邮箱:xxxx@xxx.xxx
公司:xxxx有限公司
职位:xx工程师
Java使用年限:x年

[推荐]甲骨文官网Java故障排查向导

甲骨文官网的Java故障排查向导比较全面地总结了面对各种Java故障时,该如何应对。推荐给大家。

Java平台 标准版 故障排查 向导 

下面摘要部分链接:

2 Diagnostic Tools

3 Troubleshoot Memory Leaks

Part II Debug JVM Issues

5 Troubleshoot System Crashes

6 Troubleshoot Process Hangs and Loops

7 Handle Signals and Exceptions

17 Submit a Bug Report

Part VI Appendix

A Fatal Error Log

C Environment Variables and System Properties

D Command-Line Options

E Summary of Tools in This Release

GreenTeaJUG 活动 第24期 杭州

时间:2016-09-11 14:00-18:00
地点:西湖区古墩路99号 浙商财富中心1号楼蘑菇街 5楼牛津大学会议厅(前台有引导)
组织:@JianhaoMo  、蘑菇街七公

时间:2016-09-11 14:00-15:00
主题:MWP DSL
讲师:刘昱接 (吴邪@美丽联合集团)

时间:2016-09-11 15:00-18:00
主题:Cloud Native Java
讲师:Josh Long(@Josh Long

Josh Long 是 Pivotal 公司的 Spring 核心开发者和布道者,他是 Java Champion,5 本书的作者(包括即将出版的 O’Reilly 图书 “Cloud Native Java: Designing Resilient Systems with Spring Boot, Spring Cloud, and Cloud Foundry”),多个知名开源项目(Spring Boot, Spring Integration, Spring Cloud, Activiti 和 Vaadin)的 commiter。

两小时全程 live coding, Josh 带你领略如何基于 Spring Boot & Spring Cloud 开发云端微服务!
在组织中,一件工作从前往后流动,直到部署上线并实现价值,这需要时间。如何缩短这段时间往往是组织生死存亡的关键,对于很多组织和行业来说,软件就是核心竞争力。
组织将大型的目标拆解成小型的、可独立部署的、关注功能点的目标,或者说微服务。为了尽可能缩短各个团队之间沟通的时间,组织慢慢压缩转变,并尽可能地自动化,开发和运维开始做 “devops“ 了,基于云的服务和平台(如 Cloud Foundry)自动化了大量运维工作,改变了管理方式。
然而,高速是伴随危险的,微服务带来了组织必须要面对的架构复杂度。在本次分享中,我们会看一下那些高效的组织如 Ticketmaster 和 Netflix 如何使用 Spring Boot 和 Spring Cloud 来解决这些复杂度。

报名

活动报名请按照如下格式发邮件到event@greenteajug.cn
主题:GreenTeaJUG活动 第24期 杭州
姓名:XXX
手机号码:xxxxxxxxxxx
邮箱:xxxx@xxx.xxx
公司:xxxx有限公司
职位:xx工程师
Java使用年限:x年

20160821关于g1讨论整理

莫简豪 20:26

many people curious about g1. Most apps still use cms. How does g1 perform in real production?

@Martijn Verburg @Monica Beckwith  hope you can give us some infomation

Monica Beckwith 21:01

Sure. If you have any specific use cases I can help. All companies that I worked with, that are able to get to latest JDK 8 release are happy moving to G1… with minimal tuning.

Martijn Verburg 21:34

Kirk and I are presenting our tuning G1 talk at JavaOne. I will post some of our current findings here over the weekend. We have found some usage patterns and edge cases where G1 has some challenges. It also is a good idea to track the open issues on the OpenJDK JIRA labelled with G1. You will see that there are many small fixes and improvements to go.

We would only recommend it for Java 8u91 as there are still JVM crash bugs prior to that

Humongous objects still cause big problems and there are hard limits to reference processing and object copy times depending on the shape of your object graph

ayanamist 22:08

Will g1gc has the ability to do parallel fullgc? Google has a patch for cms to enable parallel fullgc which brings quite a lot enhancement.

e.g. HBase, using BlockCache & MemStore, consumes a lot of heap space, and eventually has a fullgc after not a long time, which affects service availability when heap is large than 100GB. So concurrent fullgc is valuable in this case.

Martijn Verburg 22:18

IIRC the G1 full GC is currently single threaded but they are working on making it parallel. It is not concurrent by design (it has to stop all threads at a safe point). Monica will correct me if I’m wrong 🙂

I’m not yet convinced that G1 works all that well for heaps > 75GB. In *theory* a fully production read Shenandoah will perform better and of course the C4 collector still wins hands down.

That said there are still ~50 G1 bugs and features that they are working on, so I expect it it improve

Monica Beckwith 22:20

I have worked with Hbase and blockcache and memstore with G1 with about 64Gs no full GCs

Martijn Verburg 22:20

Yeah we typically see 64GB heaps for that sort of work

But unless you’re on the latest 8 update we’ve seen instabilities over several weeks of hot running

And of course with G1 the big question is what pause time goals you want 🙂. It’s a great low pause collector but not a low latency low pause collector (if you’re in the high frequency trading business)

Monica’s work on G1 is putting many of us out of a job 😉

One last note before I jump on my next plane. You can still get better extreme low latency out of a well tuned CMS than you can G1. However it takes a lot of work and tuning of many parameters.

This is why RedHat, Google, Twitter, ourselves and a few others will try to maintain CMS for Java 10 – but I think G1 will take over for a majority of applications who want good low pause behaviour with minimal tuning

Monica Beckwith 22:35

Agreed on low latency CMS surpasses G1 because you don’t have any old gen “collection” and you can easily avoid/push off full GCs…

(With CMS)

BTW, yes all full GCs in HotSpot are stop the world and so far only Parallel GC employs multiple threads for full collections

ayanamist 22:57

Param tuning is not a big problem in many company, but the best gc effect after tuning is.

Monica Beckwith 23:00

Ok. I understand. What is the live data set size for your 100g heap?

ayanamist 23:00

Yes we do not encounter fullgc on 64GB heap with forked but not community hbase 0.94 even on openjdk 6. But since larger heap brings out more problems, our hbase team is splitting hbase server to small unit using docker to decrease heap size.

@Monica Beckwith Also large than 64G. We have some 196G mem machines.

Reducing heap size and increasing unit count is not a ideal solution. It brings more work on operation and more mem overhead. So if jdk can improve its full gc performance, it will bring a lot wonderful things.

Monica Beckwith 23:04

Ok. We can work on this via email if you prefer… but if you could send more information on LDS and marking threshold and occupancy… it will give me a better idea of the workload pressure on G1

ayanamist 23:09

@Monica Beckwith Fine, i will forward this to our hbase team

Martijn Verburg 23:29

And please do grab a free trial copy of censum from Jclarity.com – it will help you compare and contrast your GC behaviour before and after changes.

java8 API (一) (String、正则、IO、集合)

前言

目的

  • java8自14年发布已经过去2年多了,越来越多的应用,开始升级到java8,升级不是目的,目的是升级之后,我们就可以使用java8新增的特性,从而提高开发效率、性能、稳定性等。所以伴随着升级,在团队内分享了java8的新特性,不过光了解新特性,知道lambda是啥,真正实践的时候还是有些迷茫(我自己现在就是这样),所以最近开始慢慢的整理java8新增的api,一方面字节在学习,另一方面通过例子的形式,希望可以帮助大家了解新增的api,以及api如何与lambda&stream等新特性应用在开发中。文章中不包含的内容:
    • java8新特性和语法讲很少,如果对java8还不太了解可以先自己查阅学习。
    • 文中例子都比较简单,代码以lambda和stream的代码为主,java8之前的代码例子基本没有,脑补一下,大家都能想出来。
  • 文中例子,都是自己敲过一遍,并且运行出的结果,如果大家发现问题,或者有更好的例子等都欢迎大家随时反馈给我@有光。

java8新增的API

  • 非官方数据
    • 195个新的文件加入到 JDK8 API
    • 93 新类, 89 新接口 , 13 新enum
    • 2699 新方法, 56 新构造函数
    • 46 个接口标记为函数式接口
    • 213 接口默认方法
    • 68 接口静态方法

基础

String

join()

  • 字符串拼接。
        String.join(":", "alibaba", "icbu", "youguang");
        String join = String.join(":", Lists.newArrayList("alibaba", "icbu", "youguang"));
        System.out.println(join);// => alibaba:icbu:youguang

chars()

  • 创建一个字符流。
  • 例子:统计去重后的字符数.
        long collect = "alibaba:icbu:youguang".chars()//
                                              .distinct()//
                                              .count();
        System.out.println(collect);// => 11

StringJoiner

  • 字符串拼接。
  • PS:String.join方法内部就是用StringJoiner实现的。
         StringJoiner sj = new StringJoiner(":");
        sj.add("alibaba");
        sj.add("icbu");
        sj.add("youguang");
        String result = sj.toString(); //alibaba:icbu:youguang

        sj = new StringJoiner(":","prefix-", "-suffix");
        sj.add("alibaba");
        sj.add("icbu");
        sj.add("youguang");
        System.out.println(sj.toString()); //prefix-alibaba:icbu:youguang-suffix

正则

Pattern.splitAsStream()

  • 正则分割后的结果,通过流来操作。
  • 例子:冒号分割,过滤掉youguang
        String bar = Pattern.compile(":")
                            .splitAsStream("alibaba:icbu:youguang")
                            .filter(s -> !s.contains("youguang"))
                            .collect(Collectors.joining(":"));
        System.out.println(bar);// => alibaba:icbu

Pattern.asPredicate()

  • 通过正则生成Predicate。
  • 例子:结合stream来过滤字符串。
      Pattern pattern = Pattern.compile(".*@gmail\\.com");
        Stream.of("tony.liw@gmail.com", "tony.liw@alibaba-inc.com")
              .filter(pattern.asPredicate())
              .count();// => 1

数学操作

输入&输出

  • java8提供了更简单的方式进行文件操作。

Files.list

  • Files类从1.7引入,1.8增加list方法生成stream来操作文件/目录。
  • PS:此处使用了1.7中的try-with-resource语法(Stream实现了AutoCloseable接口)
        try (Stream<Path> stream = Files.list(Paths.get("/opt"))) {
            String joined = stream.map(String::valueOf)//
                    .filter(path -> !path.startsWith("."))//
                     .sorted().collect(Collectors.joining("; "));
            System.out.println("List: " + joined);// => List: /opt/cisco; /opt/local

Files.find

  • 查找文件
  • 例子: 找到目录下的所有JavaScript文件(目录查找深度不超过5)。
        Path start = Paths.get("/home/admin/");
        int maxDepth = 5;//目录树层数
        try (Stream<Path> stream = Files.find(start, maxDepth, (path, attr) ->
                String.valueOf(path).endsWith(".js"))) {

            String joined = stream
                    .sorted()
                    .map(String::valueOf)
                    .collect(Collectors.joining("; "));
            System.out.println("Found: " + joined);
        }

Files.walk

  • 遍历文件,下面例子实现与上面的find同样的功能,不同的是过滤JavaScript文件通过stream的filter实现。
        Path start = Paths.get("/home/admin/");
        int maxDepth = 5;//目录树层数
        try (Stream<Path> stream = Files.walk(start, maxDepth)) {
            String joined = stream
                    .map(String::valueOf)
                    .filter(path -> path.endsWith(".js"))
                    .sorted()
                    .collect(Collectors.joining("; "));
            System.out.println("walk(): " + joined);
        }

Files.readAllLines

  • 读取文件的所有内容
List<String> lines = Files.readAllLines(Paths.get("res/nashorn.js"));
lines.add("print('foobar');");
Files.write(Paths.get("res/nashorn1-modified.js"), lines);

PS:使用该方法的时候要考虑到文件的大小,该方法会将所有内容一次读入内存。

Files.lines

  • 将文件内容转成stream,元素是每行的内容。
       try (Stream<String> stream = Files.lines(Paths.get("res/nashorn.js"))) {
            stream
                    .filter(line -> line.contains("print"))
                    .map(String::trim)
                    .forEach(System.out::println);
        }

Files.newBufferedReader&Files.newBufferedWriter

  • 带buffer的读写操作
Path path = Paths.get("res/nashorn1.js");
try (BufferedReader reader = Files.newBufferedReader(path)) {
    System.out.println(reader.readLine());
}
Path path = Paths.get("res/output.js");
try (BufferedWriter writer = Files.newBufferedWriter(path)) {
    writer.write("print('Hello World');");
}

NULL(空指针)

  • 如何避免NullPointerException,为了避免NPE,写代码过程!=null检查会出现在各种地方,java8引入了更好的解决方案(Optional+Lambda)。其他语言解决NPE的语法糖

Optional基本

    //不要这样,这与!=null没什么区别
    if(stringOptional.isPresent()){
         System.out.println(stringOptional.get().length());
    }
    //下面是推荐的常用操作

    optionalValue.ifPresent(s -> System.out.println(s + " contains red"));
    //增加到集合汇总
    optionalValue.ifPresent(results::add);
    //增加到集合中,并返回操作结果
    Optional<Boolean> added = optionalValue.map(results::add);

    //无值的optional
    Optional<String> optionalString = Optional.empty();
    //不存在值,返回“No word”
    String result=optionalValue.orElse("No word");
    //没值,计算一个默认值
    result = optionalString.orElseGet(() -> System.getProperty("user.dir"));
    //无值,抛一个异常
    try {
        result = optionalString.orElseThrow(NoSuchElementException::new);
    } catch (Throwable t) {
    }   

Optional.map

  • 例子:看代码应该秒懂了,就是取foo值,但是为了取这个值,正常的逻辑里面需要增加一串!=null检查。java8中可以通过map函数避免。
//老的写法
Outer outer = new Outer();
if (outer != null && outer.nested != null && outer.nested.inner != null) {
    System.out.println(outer.nested.inner.foo);
}
//新的写法
Optional.of(new Outer())
    .map(Outer::getNested)
    .map(Nested::getInner)
    .map(Inner::getFoo)
    .ifPresent(System.out::println);

//第二种lambda的方式
resolve(() -> obj.getNested().getInner().getFoo())
    .ifPresent(System.out::println);

public static <T> Optional<T> resolve(Supplier<T> resolver) {
    try {
        T result = resolver.get();
        return Optional.ofNullable(result);
    }
    catch (NullPointerException e) {
        return Optional.empty();
    }
}

集合

Collection

removeIf

  • 通过传入Predicate删除集合里面符合条件的元素。
        Collection<String> c = new HashSet<>();
        c.add("Content 1");
        c.add("Content 2");
        c.add("Content 3");
        c.removeIf(s -> s.contains("2"));
        System.out.println(c);// => [Content 3, Content 1]
  • PS:如果这个接口可以满足过滤的要求,就没必要使用stream了,这个效率更好。
  • 扩展:充分利用Predicate,直接看例子
//基本操作
 list =new ArrayList(Arrays.asList(1,2,3,4,5,6,7,8,9,10,11));
 list.removeIf(a->{ return a%3==0;});

 //OR 操作
 Predicate<Integer> predicate2 = a->{ return a % 3 == 0;};
 Predicate<Integer> predicate3 = a->{ return a % 5 == 0;};
 list =new ArrayList(Arrays.asList(1,2,3,4,5,6,7,8,9,10,11));
 list.removeIf(predicate2.or(predicate3));

 //AND 操作
 Predicate<Integer> predicate2 = a->{ return a % 3 == 0;};
 Predicate<Integer> predicate3 = a->{ return a % 5 == 0;};
 list =new ArrayList(Arrays.asList(1,2,3,4,5,6,7,8,9,10,11));
 list.removeIf(predicate2.and(predicate3));

stream、parallelStream

  • 大家都知道了,就不说了,记住所有集合类都是通过Collection接口继承来即可。

Iterable

forEach

  • 遍历每个元素,继承了Iterable接口的都可以使用。
 List<String> stringList = Arrays.asList("a", "b");
        stringList.forEach(System.out::println);

iterator

forEachRemaining

  • 遍历iterator,并根据指定的action进行处理。开发中可能会出现,需要对集合中的第一个或者前几个元素进行特别的操作,然后继续遍历剩余的元素执行另一个操作(action),这个时候使用forEachRemaining非常合适。例如下面字符串拼接的例子。
        if (!iterator.hasNext()) {
            return;
        }
        StringBuilder builder = new StringBuilder();
        builder.append(iterator.next());
        iterator.forEachRemaining( element -> {
            builder.append(", ").append(element);
        });
  • PS:这里只是说明一下用法,字符串拼接,当然用String.join就够啦。

List

replaceAll

  • 传入UnaryOperator,将元素替换为一元操作之后的值
   List<String> stringList = Arrays.asList("a", "b", "c");
        stringList.replaceAll(String::toUpperCase);
        System.out.println(stringList);//[A, B, C]

sort

  • 通过指定Comparator进行排序,参数为空则根据自然排序。
        List<String> stringList = Arrays.asList("a", "b", "c");
        stringList.sort(String::compareTo);
  • PS: 可能会有人问这个和Collections.sort()的区别。下面是Collections的sort方法代码。内部调用的就是list.sort
  public static <T extends Comparable<? super T>> void sort(List<T> list) {
        list.sort(null);
    }

Set

  • 接口没什么变化。

Map

foreach

       Map<String, Integer> map = new HashMap<>();
        map.put("A", 10);
        map.put("B", 20);
        map.put("C", 30);
        map.forEach((k, v) -> System.out.println("Item : " + k + " Count : " + v));

getOrDefault

  • 根据key取value,没有返回一个默认值(这个一直是很多人想要的方法)。
System.out.println(map.getOrDefault("D",40));// => 40
  • PS:如果还在使用Apache Commons Collections包中的DefaultedMap类,更换了。

putIfAbsent

  • javadoc中提供了与putIfAbsent的等价方法,
  • 特别说明put方法返回值:对应的key曾经有值返回老的value,否则返回null
    //The default implementation is equivalent to, for this map:
       V v = map.get(key);
      if (v == null)
          v = map.put(key, value);
    
      return v;
    
  • 例子:
        System.out.println(map.putIfAbsent("B",40));// => 20
        System.out.println(map.putIfAbsent("D",40));// => null
    

remove(Object.Object)

  • key和valu都相等的时候才删除,下面是javadoc中原来等价方法实现。
      if (map.containsKey(key) && Objects.equals(map.get(key), value)) {
          map.remove(key);
          return true;
      } else
          return false;
  • 例子:
 System.out.println(map.remove("D",40));// => true

replace(K,V)

  • map中包含这个key,替换对应的value。javadoc中原来等价的方法实现
      if (map.containsKey(key)) {
          return map.put(key, value);
      } else
          return null;
  • 例子:Map<String, Integer> map = new HashMap<>(); map.put("A", 10); System.out.println(map.replace("A",20));//=> 10
  • PS:注意与putIfAbsent区别

replace(K,V,V)

  • map中包含这个key,并且value相等时,替换对应的value。javadoc中原来等价的方法实现
      if (map.containsKey(key) && Objects.equals(map.get(key), value)) {
          map.put(key, newValue);
          return true;
      } else
          return false;
  • 例子:
        Map<String, Integer> map = new HashMap<>();
        map.put("A", 10);
        map.put("B", 20);
        System.out.println(map.replace("B",10,100));//=>false
        System.out.println(map.replace("B",20,100));//=> true

compute(K,remappingFunction)

  • 通过remappingFunction函数,根据指定的key和对应的value,通过计算生成新的value。javadoc中原来等价的方法实现
      V oldValue = map.get(key);
      V newValue = remappingFunction.apply(key, oldValue);
      if (oldValue != null ) {
         if (newValue != null)
            map.put(key, newValue);
         else
            map.remove(key);
      } else {
         if (newValue != null)
            map.put(key, newValue);
         else
            return null;
      }
  • 例子:统计单词出现次数/统计图书借阅次数/遇到同样的key,创建或者append一个msg信息等。
        Map<String, Integer> countMap = Maps.newHashMap();
        List<String> bookList= Arrays.asList("Book-A", "Book-B", "Book-A");
        for (String book : bookList) {
            countMap.compute(book, (k, v) -> v == null ? 1 : v + 1);
        }
        System.out.println(countMap);
  • PS:要注意如果remappingFunction计算结果为空,会从map中remove

computeIfAbsent(K,mappingFunction)vs computeIfPresent(K,remappingFunction)

  • 这两个方法比较相近容易混淆,对比一下,下面是javadoc中两个新方法等同老代码。左侧:computeIfAbsent,右侧:computeIfPresent screenshot
  • 区别:
    • computeIfAbsent value根据key计算。computeIfPresent value基于key和oldValue计算(参数名也可以看出点意思mappingFunction/remappingFunction)
    • newValue为空,computeIfPresent会删除map中的元素。
  • 例子:这两个方法很容易想到的一个场景是本地缓存(考虑到多线程场景可以使用ConcurrentHashMap),下面以computeIfAbsent方法为例,同时与java8之前的版本代码做一下对比。
    
    static Map<String, Integer> CACHE = new ConcurrentHashMap<>();
    
    public Integer  getJAVA8(String key){
        //java8会使用thread-safe的方式从cache中存取记录
       return CACHE.computeIfAbsent(key, s -> {
           int rt=0;
           //xxx 计算 rt=
           return rt;
       });
    }
    
    public Integer  getJAVA7(String key){
    
        Integer rt = CACHE.get(key);
    
        if (rt == null) {
            //java8 中ConcurrentHashMap复写了computeIfAbsent方法做了线程安全控制
            synchronized (CACHE) {
                rt = CACHE.get(key);
                if (rt == null) {
                    //xxxx计算 rt=
                    CACHE.put(key, rt);
                }
            }
        }
        return rt;
    }
    

merge(K,V,remappingFunction)

  • 看名字已经理解80%了,直接看javadoc中与老版本等价的代码好了。
      V oldValue = map.get(key);
      V newValue = (oldValue == null) ? value :
                   remappingFunction.apply(oldValue, value);
      if (newValue == null)
          map.remove(key);
      else
          map.put(key, newValue);
  • 是不是一眼看过去和computeIfPresent很像。此处diff一下就清晰了,computeIfPresent是在key对应的value存在时才有效。 screenshot

replaceAll(function)

  • 根据function计算结果,替换map所有entry的value

Comparator

  • Comparator在平时开发中用的比较多,java8针对该接口,增加了16个默认方法和静态方法,下面挑一些跟大家分享。

comparing(keyExtractor)

  • 先看例子,生成根据firstName对Person进行排序的Comparator:
        //老写法
        Comparator<Person> comparator=new Comparator<Person>() {
    
            @Override
            public int compare(final Person o1, final Person o2) {
                return o1.name.compareTo(o2.name);
            }
        };
        //lambda 写法
        comparator= (o1, o2) -> o1.name.compareTo(o2.name);
        //Comparator.comparing方法,提供提取比较key的function即可
        comparator= Comparator.comparing(Person::getName);
    
  • PS:该方法,要求提取的key实现了 Comparable接口。key没有Comparable接口可以使用重载实现comparing(keyExtractor,keyComparator)
  • 重载方法:
    • comparing(keyExtractor,keyComparator)
    • comparingInt(keyExtractor) 提取的key是Integer类型
    • comparingLong(keyExtractor)
    • comparingDouble(keyExtractor)

reversed()

  • 反转比较规则
        List<Integer> integerList = Arrays.asList(1, 3, 2, 5, 4);
        //正序
        integerList.sort(Integer::compareTo);
        System.out.println(integerList); // => [1, 2, 3, 4, 5]
        //倒序
        integerList.sort(Comparator.comparing(Integer::intValue).reversed()); // => [5, 4, 3, 2, 1]

thenComparing(other)

  • 链式比较,以后不用在使用第三方的ComparisonChain类了。
  • 例子:先按字符串长度,再按字符默认顺序排序(忽略大小写)。
 Comparator<String> cmp = Comparator.comparingInt(String::length)
                                              .thenComparing(String.CASE_INSENSITIVE_ORDER);
  • 重载方法
    • thenComparing(keyExtractor,keyComparator)
    • thenComparing(keyExtractor)
    • thenComparingInt(keyExtractor)
    • thenComparingLong(keyExtractor)
    • thenComparingDouble(keyExtractor)

reverseOrder

  • 静态方法,返回与自然排序相反的Comparator(比较元素要实现Comparator接口)
        List<Integer> integerList2 = Arrays.asList(1, 3, 2, 5, 4);
        integerList.sort(Comparator.reverseOrder());
        System.out.println(integerList);// => [5, 4, 3, 2, 1]

naturalOrder

  • 与reverseOrder相反,默认的自然排序器。等价//c1.compareTo(c2);

nullsFirst(comparator) & nullsLast(comparator)

  • 针对null值指定策略,排在前面(nullsFirst),还是后面(nullsLast)
        List<Integer> integerList3 = Lists.newArrayList(1, 3, null, 5, 4);
        integerList3.sort(Comparator.nullsFirst(Integer::compareTo));
        System.out.println(integerList3);// => [null, 1, 3, 4, 5]
        integerList3.sort(Comparator.nullsLast(Integer::compareTo));
        System.out.println(integerList3);// => [1, 3, 4, 5, null]
  • 这两个比较器一个很大的作用是可以处理结合中有null值的情况,一般默认的比较器遇到null都会抛出NPE,如果不想NPE可以使用nullsFirst/nullsLast包装一下。上面例子:如果不通过Comparator.nullsFirst(Integer::compareTo)生成新的比较器,直接使用Integer::compareTo就会抛NPE异常。

Arrays

  • 工具类中增加了一些对数组相关的流和并行处理的操作。

Stream

  • 将数组转成流进行操作,这样Stream Api就都可以用了stream api
//数组内容求和
int[] array = new int[]{1,2,3,4,5};
//求和
Arrays.stream(array).sum()
//过滤
int[] ms = Arrays.stream(ns).map(n -> n * 2).filter(n -> n % 4 == 0).toArray();

setAll

  • setAll方法提供一个 int -> T的函数接口做参数,int是数组的索引,T是数组的新值。
  • 例子:通过该接口对数组的索引进行操作,然后将指定数组当前索引位置的值赋值为操作后的值。
        int[] array = new int[10];
        Arrays.setAll(array, i -> i * 10);
        System.out.println(Arrays.toString(array));// => 输出 [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]        

spliterator

Collections

  • emptySortedSet、emptySortedMap、emptyNavigableSet、emptyNavigableMap、unmodifiableNavigableSet、unmodifiableNavigableMap、synchronizedNavigableSet、synchronizedNavigableMap等。

集合&数组转化

数组转集合

  • 没发现java8有什么新增的方式,如果有同学知道的求推荐。老的方式(Arrays/Guava包):
        List<Integer> integerList = Arrays.asList(1, 2, 3, 4);
        // guava
        integerList = Lists.newArrayList(1, 2, 3, 4);

集合转数组

  • 看例子
        //原始方式
        Integer[] integerArray = integerList.toArray(new Integer[integerList.size()]);
        // guava
        int[] intArray = Ints.toArray(integerList);
        // java8-基本类型
        intArray = integerList.stream().mapToInt(Integer::intValue).toArray();
         // java8-对象类型
        stringArray = stringList.stream().toArray(String[]::new);
Character[] characterArray = stringList.stream().map(s -> s.charAt(0)).toArray(Character[]::new);

未完待续

  • java8 API (二) stream整理中

推荐一个终端获取jmx信息的小工具——jmxterm

作者@JianhaoMo

最近由于某些原因跟同学推荐了下jmxterm,发现还是不少同学不知道有这么个工具,所以在这里推荐下。

官网:http://wiki.cyclopsgroup.org/jmxterm/

jmxterm是本地命令行看jmx的工具,jdk7以上自带的jcmd命令可以动态打开关闭本地jmx

举例看codecache:

jcmd <pid> ManagementAgent.start_local

echo “get -d java.lang -b name=Code\ Cache,type=MemoryPool Usage” |  java -jar jmxterm-1.0-alpha-4-uber.jar -l <pid> -v silent -n

jcmd <pid> ManagementAgent.stop

fastjson 1.2.10版本发布,修复Bug,支持Class Level SerializeFilter

作者:温绍锦(@温高铁)阿里巴巴资深技术专家

Bug Fixed

  1. 修复ValueFilter导致序列化数据丢失的问题,这个在1.2.9优化序列化引起。
  2. 修复某些场景下解析json中的注释出错。issue 559
  3. 修复WriteNonStringValueAsString特性打开时,非public类序列化会导致int类型输出为0的问题。 issue 572
  4. 修复1.2.8/1.2.9版本不支持JDK 1.5的问题

功能增强

  1. 新增Class Level SerializeFilter支持,在此之前只能在toJSONString时SerializeFilter,对所有的类型都起作用,这样会对框架的实现由性能影响,新特性允许SerializeFilter注册在类型上,具体文档看这里https://github.com/alibaba/fastjson/wiki/Class_Level_SerializeFilter

相关链接