JDK8新特性(二)

一宝惰、方法引用與構造函數(shù)引用

  • 說明:方法引用是?種更簡潔易懂的lambda表達式钟些,操作符是雙冒號::,用來直接訪問類或者實例已經存在的方法或構造方法
  • 通過方法引用,可以將方法的引?賦值給?個變量
  • 語法:左邊是容器(可以是類名鳖敷,實例名),中間是" :: "程拭,右邊是相應的方法名
    1. 靜態(tài)方法定踱,則是ClassName::methodName。如 Object ::equals
    2. 實例方法恃鞋,則是Instance::methodName
    3. 構造函數(shù)崖媚,則是 類名::new;
  • 單個參數(shù)
    Function<入?yún)?, 返回類型> func = 方法引用
    應用 func.apply(入?yún)?;
  • 兩個參數(shù)
    BiFunction<入?yún)?,入?yún)?, 返回類型> func = 方法引用
    應用 func.apply(入?yún)?,入?yún)?);
class User {
    private String username;
    private Integer age;
    public User() {}
    public User(String username) {
        this.username = username;
    }
    public User(String username, Integer age) {
        this.username = username;
        this.age = age;
    }
 }

public class Test{

    public static void main(String[] args) {
        // 使用雙冒號::來構造靜態(tài)函數(shù)引用
        Function<String, Integer> fun = Integer::parseInt;
        Integer value = fun.apply("1024");
        System.out.println(value);
        // 使用雙冒號::來構造非靜態(tài)函數(shù)引用
        String content = "測試使用";
        Function<Integer, String> func = content::substring;
        String result = func.apply(1);
        System.out.println(result);
        // 構造函數(shù)引用,多個參數(shù)
        BiFunction<String, Integer, User> biFunction = User::new;
        User user1 = biFunction.apply("Test", 28);
        System.out.println(user1.toString());
        //構造函數(shù)引用山宾,單個參數(shù)
        Function<String, User> function = User::new;
        User user2 = function.apply("Test");
        System.out.println(user2.toString());
        // 函數(shù)引用也是一種函數(shù)式接用至扰,可以將函數(shù)引用作為方法的參數(shù)
        sayHello(String::toUpperCase, "Test");
    }
    
    /**
     *
     * @param func 函數(shù)引用
     * @param param 對應的參數(shù)
     */
    private static void sayHello(Function<String, String> func, Stringparam) {
        String result = func.apply(param);
        System.out.println(result);
    }

}

二鳍徽、JDK8之流Stream

  • Stream 中文稱為 “流”资锰,通過將集合轉換為這么?種叫做 “流”的元素隊列,通過聲明性方式阶祭,能夠對集合中的每個元素進行?系列并行或串行的流水線操作绷杜。
  • 元素是特定類型的對象,所以元素集合看作?種流濒募, 流在管道中傳輸鞭盟, 且可以在管道的節(jié)點上進行處理, ?如 排序瑰剃,聚合齿诉,過濾等操作。


    image.png
  • 操作詳情
    1. 數(shù)據(jù)元素便是原始集合晌姚,如List粤剧、Set、Map等
    2. 生成流挥唠,可以是串行流stream() 或者并行流 parallelStream()
    3. 中間操作抵恋,可以是 排序,聚合宝磨,過濾弧关,轉換等
    4. 終端操作,很多流操作本身就會返回?個流唤锉,所以多個操作可以直接連接起來世囊,最后統(tǒng)?進行收集
List<String> list = Arrays.asList("aaaa","bbbb","cccc","dddd","eeee);
List<String> resultList = list.stream().map(obj->"遍歷:"+obj).collect(Collectors.toList());
System.out.println(resultList);

三、JDK8之流操作map和filter函數(shù)

  • map函數(shù)
    1. 將流中的每?個元素 T 映射為 R(類似類型轉換)
    2. 類似遍歷集合窿祥,對集合的每個對象做處理
    3. 場景:轉換對象株憾,如javaweb開發(fā)中集合里面的DO對象轉換為DTO對象
List<String> list = Arrays.asList("aaaa","bbbb","cccc","dddd","eeee);
List<String> resultList = list.stream().map(obj->"遍歷:"+obj).collect(Collectors.toList());
System.out.println(resultList);
@Data
class User {
    private String name;
    private Integer age;
    public User(String name, Integer age) {
        this.name= name;
        this.age = age;
    }
}

@Data
class UserDTO {
    private String name;
    private Integer age;
    public User(String name, Integer age) {
        this.name= name;
        this.age = age;
    }
}

public class Test{
    public static void main(String[] args) {
        List<User> list = Arrays.asList(new User("peter",11),new User("jack",12),new User("tom",10),new User("marry",14));
        List<UserDTO> userDTOList = list.stream().map(obj->{
            UserDTO userDTO = new UserDTO(obj.getName(),obj.getAage());
            return userDTO;
        }).collect(Collectors.toList());
        System.out.println(userDTOList);
    }
}
  • filter函數(shù)
    1. 用于通過設置的條件過濾出元素
    2. 場景:主要用于篩選過濾出符合條件的元素
List<String> list = Arrays.asList("springboot", "springcloud","redis", "git", "netty", "java", "html", "docker");
List<String> resultList = list.stream().filter(obj -> obj.length() >5).collect(Collectors.toList());
System.out.println(resultList);

四、JDK8之流操作limit和sorted函數(shù)

  • limit函數(shù)
    1. 截斷流使其最多只包含指定數(shù)量的元素
List<String> list = Arrays.asList("springboot", "springcloud","redis", "git", "netty", "java", "html", "docker");
//limit截取
List<String> resultList=list.stream().sorted(Comparator.comparing(String::length).reversed()).limit(3).collect(Collectors.toList());
System.out.println(resultList);
  • sorted函數(shù)
    1. sorted() 對流進?自然排序, 其中的元素必須實現(xiàn)Comparable 接口
    2. sorted(Comparator<? super T> comparator) 用來自定義升降序
List<String> list = Arrays.asList("springboot", "springcloud","redis", "git", "netty", "java", "html", "docker");
List<String> resultList1 = list.stream().sorted().collect(Collectors.toList());
List<String> resultList2 = list.stream().sorted(Comparator.comparing(obj -> obj.length())).collect(Collectors.toList());
List<String> resultList3 = list.stream().sorted(Comparator.comparing(obj ->obj.length(),Comparator.reverseOrder())).collect(Collectors.toList());
List<String> resultList4 = list.stream().sorted(Comparator.comparing(String::length).reversed()).collect(Collectors.toList());

五壁肋、JDK8之流操作allMatch和anyMatch函數(shù)

  • allMatch函數(shù)
    1. 檢查是否匹配所有元素号胚,只有全部符合才返回true
List<String> list = Arrays.asList("springboot", "springcloud", "redis","git", "netty", "java", "html", "docker");
boolean flag = list.stream().allMatch(obj->obj.length()>1);
System.out.println(flag);
  • anyMatch函數(shù)
    1. 檢查是否?少匹配?個元素
List<String> list = Arrays.asList("springboot", "springcloud", "redis","git", "netty", "java", "html", "docker");
boolean flag = list.stream().anyMatch(obj->obj.length()>18);
System.out.println(flag)

六籽慢、JDK8之流操作max和min函數(shù)

  • max和min函數(shù)
  1. 最大值和最小值
@Data
class Student {
    private int age;
    public Student(int age) {
        this.age = age;
    }
}

public class Test{
    public static void main(String[] args) {
        List<Student> list = Arrays.asList(new Student(32),newStudent(33),new Student(21),new Student(29),new Student(18));
        //最大值
        Optional<Student> optional = list.stream().max((s1, s2)->Integer.compare(s1.getAge(),s2.getAge()));
        //最小值
        Optional<Student> optional = list.stream().min((s1, s2)->Integer.compare(s1.getAge(),s2.getAge()));
        System.out.println(optional.get().getAge());
    }
}

七、JDK8之并行流parallelStream

  • 為什么會有這個并行流
    1. 集合做重復的操作猫胁,如果使?串行執(zhí)行會相當耗時箱亿,因此?般會采用多線程來加快, Java8的paralleStream用fork/join框架提供了并發(fā)執(zhí)行能力弃秆。
    2. 底層原理
      (1) 線程池(ForkJoinPool)維護?個線程隊列
      (2) 可以分割任務届惋,將父任務拆分成子任務,完全貼合分治思想
//順序輸出
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
numbers.stream().forEach(System.out::println);
//并?亂序輸出
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
numbers.parallelStream().forEach(System.out::println);
  • paralleStream并行是否?定比Stream串行快菠赚?
    1. 錯誤脑豹,數(shù)據(jù)量少的情況,可能串行更快衡查,F(xiàn)orkJoin會耗性能
    2. 多數(shù)情況下并行比串行快瘩欺,是否可以都用并行
      (1) 不行,部分情況會有線程安全問題拌牲,parallelStream里?使用的外部變量俱饿,比如集合?
      定要使用線程安全集合,不然就會引發(fā)多線程安全問題塌忽。
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());
 }
image.png

image.png

八拍埠、JDK8之reduce操作

  • 什么是reduce操作

    1. 聚合操作,中文意思是 “減少”
    2. 根據(jù)?定的規(guī)則將Stream中的元素進行計算后返回?個唯?的值
  • 常用方法一

Optional<T> reduce(BinaryOperator<T> accumulator);

//accumulator 計算的累加器
//例子: 第?個元素相加和第?個元素相加土居,結果再和第三個元素相加枣购,直到全部相加完成
int value = Stream.of(1, 2, 3, 4, 5).reduce((item1, item2) -> item1+ item2).get();

//不?lambda的寫法
int result = Stream.of(1,2,3,4,5).reduce(new BinaryOperator<Integer>() {
    @Override
    public Integer apply(Integer item1, Integer item2) {
        return item1 + item2;
    }
 }).get();
  • 常用方法二
T reduce(T identity, BinaryOperator<T> accumulator);

//identity ?戶提供?個循環(huán)計算的初始值
//accumulator 計算的累加器
//例子: 100作為初始值,然后和第?個元素相加擦耀,結果在和第?個元素相加棉圈,直到全部相加完成
int value = Stream.of(1, 2, 3, 4,5).reduce(100, (sum, item) -> sum + item);
  • 例子應用
int value = Stream.of(1645, 234345, 32,44434,564534,435,34343542,212).reduce( (item1, item2) -> item1 > item2 ? item1 : item2 ).get();
System.out.println(value);

九、JDK8之集合的foreach

  • 集合遍歷的方式
    1. for循環(huán)
    2. 迭代器 Iterator
  • 注意點
    1. 不能修改包含外部的變量的值
    2. 不能用break或者return或者continue等關鍵詞結束或者跳過循環(huán)
  • Jdk8里面的新增接口
default void forEach(Consumer<? super T> action) {
    Objects.requireNonNull(action);
    for (T t : this) {
        action.accept(t);
    }
}
  • 使用案例
List<Student> results = Arrays.asList("aaaa","bbbb","ccccc","ddddd","eeeee");
results.forEach(obj->{System.out.println(obj.toString());});

十埂奈、JDK8之collector收集器

  • collect()方法的作用
    1. ?個終端操作, 用于對流中的數(shù)據(jù)進行歸集操作迄损,collect方法接受的參數(shù)是?個Collector
    2. 有兩個重載方法,在Stream接口??
 //重載?法?
 <R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R>combiner);
 //重載?法?
 <R, A> R collect(Collector<? super T, A, R> collector);
  • Collector的作用
    1. 就是收集器账磺,也是?個接口, 它的工具類Collectors提供了很多工廠方法
  • Collectors 的作用
    1. 工具類芹敌,提供了很多常見的收集器實現(xiàn)
      (1)Collectors.toList()
//ArrayList::new,創(chuàng)建?個ArrayList作為累加器
// List::add垮抗,對流中元素的操作就是直接添加到累加器中reduce操作, 對?任務歸集結果addAll氏捞,后?個子任務的結果直接全部添加到前?個子任務結果中
// CH_ID 是?個unmodifiableSet集合
 public static <T> Collector<T, ?, List<T>> toList() {
   return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,(left, right) -> {left.addAll(right); return left; }, CH_ID);
}
  1. Collectors.toMap()
  2. Collectors.toSet()
  3. Collectors.toCollection() :??定義的實現(xiàn)Collection的數(shù)據(jù)結構收集
Collectors.toCollection(LinkedList::new)
Collectors.toCollection(CopyOnWriteArrayList::new)
Collectors.toCollection(TreeSet::new)

十一、JDK8之joining函數(shù)

  • 拼接函數(shù) Collectors.joining
//3種重載?法
Collectors.joining()
Collectors.joining("param")
Collectors.joining("param1", "param2", "param3")
  • 其中?個的實現(xiàn)
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);
 }
  • 該方法可以將Stream得到?個字符串冒版, joining函數(shù)接受三個參數(shù)液茎,分別表示 元素之間的連接符、前綴和后綴。
String result = Stream.of("springboot", "mysql", "html5","css3").collect(Collectors.joining(",", "[", "]"));

十二捆等、JDK8之收集器 partitioningBy分組

  • Collectors.partitioningBy 分組滞造,key是boolean類型
public static <T> Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? superT> predicate) {
    return partitioningBy(predicate, toList());
}
  • 例子: 根據(jù)list里面進行分組,字符串長度大于4的為?組栋烤,其他為另外?組
List<String> list = Arrays.asList("java", "springboot","HTML5","nodejs","CSS3");
Map<Boolean, List<String>> result = list.stream().collect(partitioningBy(obj -> obj.length() > 4));

十三谒养、JDK8之收集器 group by分組

  • 分組 Collectors.groupingBy()
public static <T, K> Collector<T, ?, Map<K, List<T>>> groupingBy(Function<?super T, ? extends K> classifier) { 
    return groupingBy(classifier, toList());
}
  • 例子:根據(jù)學生所在的省份,進行分組
@Data
class Student {
    private String province;
    private int age;
    public Student(String province, int age) {
       this.age = age;
       this.province = province;
    }
}

public class Test{
    public static void main(String[] args) {
        List<Student> students = Arrays.asList(new Student("廣東", 23), newStudent("廣東", 24), new Student("廣東", 23),new Student("北京", 22), new Student("北京", 20), new Student("北京", 20),new Student("海南", 25));
        Map<String, List<Student>> listMap = students.stream().collect(Collectors.groupingBy(obj -> obj.getProvince()));
        listMap.forEach((key, value) -> {
            value.forEach(obj -> {
                System.out.println(obj.getAge());
            });
        });
    }
}

十四明郭、JDK8之summarizing集合統(tǒng)計

  • summarizing 統(tǒng)計相關, 下面是summarizingInt的源碼
  • 作用:可以?個方法把統(tǒng)計相關的基本上都完成
  • 分類
    1. summarizingInt
    2. summarizingLong
    3. summarizingDouble
public static <T> Collector<T, ?, IntSummaryStatistics> summarizingInt(ToIntFunction<? super T> mapper) { 
    return new CollectorImpl<T, IntSummaryStatistics, IntSummaryStatistics>(IntSummaryStatistics::new,(r, t) -> r.accept(mapper.applyAsInt(t)),(l, r) -> { l.combine(r); return l; }, CH_ID);
}
  • 例子:統(tǒng)計學生的各個年齡信息
@Data
class Student {
    private String province;
    private int age;
    public Student(String province, int age) {
       this.age = age;
       this.province = province;
    }
}

public class Test{
    public static void main(String[] args) {
        List<Student> students = Arrays.asList(new Student("廣東", 23), newStudent("廣東", 24), new Student("廣東", 23),new Student("北京", 22), new Student("北京", 20), new Student("北京", 20),new Student("海南", 25));
        IntSummaryStatistics summaryStatistics = students.stream().collect(Collectors.summarizingInt(Student::getAge));
        System.out.println("平均值:" + summaryStatistics.getAverage());
        System.out.println("人數(shù):" + summaryStatistics.getCount());
        System.out.println("最大值:" + summaryStatistics.getMax());
        System.out.println("最小值:" + summaryStatistics.getMin());
        System.out.println("總和:" + summaryStatistics.getSum());
    }
}

十五买窟、 JDK8 新的內存空間和異常處理

  • JVM 種類有很多,比如 Oralce-Sun Hotspot, Oralce JRockit, IBM J9, Taobao JVM薯定,我們講的是Hotspot才有始绍,JRockit以及J9是沒有這個區(qū)域。
  • JVM內存知識 在JDK8之前的HotSpot JVM话侄,有個區(qū)域叫做“永久代(permanent generation)亏推, 通過在命令行設置參數(shù)-XX:MaxPermSize來設定永久代最大可分配的內存空間,如果JDK8??設置了PermSize 和MaxPermSize 會被忽略并給出警告满葛。
  • 作用:該塊內存主要是被JVM?來存放 class 和 mate 信息的径簿,當 class 被加載 loader 的時候就會被存儲到該內存區(qū)中,如方法的編譯信息及字節(jié)碼嘀韧、常量池和符號解析、類的層級信息缠捌,字段锄贷,名字等。
  • 這個異常應該熟悉 java.lang.OutOfMemoryError: PermGen space曼月,原因是: 永久代空間不夠谊却,類太多導致
  • jdk8的修改 JDK8 HotSpot JVM 使用本地內存來存儲類元數(shù)據(jù)信息,叫做 元空間(Metaspace)哑芹,在默認情況下Metaspace的大小只與本地內存大小有關炎辨。
  • 常用的兩個參數(shù) -XX:MetaspaceSize=N 指Metaspace擴容時觸發(fā)FullGC的初始化閾值-XX:MaxMetaspaceSize=N 指用于限制Metaspace增長的上限,防止因為某些情況導致Metaspace無限的使用本地內存聪姿。
  • 不管兩個參數(shù)如何設置碴萧,都會從20.8M開始,然后隨著類加載越來越多不斷擴容調整直到最大末购。
  • 查看大小 jstat -gc pid MC: current metaspace capacity MU: mateaspace utilization 單位是KB破喻。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市盟榴,隨后出現(xiàn)的幾起案子曹质,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,546評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件羽德,死亡現(xiàn)場離奇詭異几莽,居然都是意外死亡,警方通過查閱死者的電腦和手機宅静,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評論 3 395
  • 文/潘曉璐 我一進店門银觅,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人坏为,你說我怎么就攤上這事究驴。” “怎么了匀伏?”我有些...
    開封第一講書人閱讀 164,911評論 0 354
  • 文/不壞的土叔 我叫張陵洒忧,是天一觀的道長。 經常有香客問我够颠,道長熙侍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,737評論 1 294
  • 正文 為了忘掉前任履磨,我火速辦了婚禮蛉抓,結果婚禮上,老公的妹妹穿的比我還像新娘剃诅。我一直安慰自己巷送,他們只是感情好,可當我...
    茶點故事閱讀 67,753評論 6 392
  • 文/花漫 我一把揭開白布矛辕。 她就那樣靜靜地躺著笑跛,像睡著了一般。 火紅的嫁衣襯著肌膚如雪聊品。 梳的紋絲不亂的頭發(fā)上飞蹂,一...
    開封第一講書人閱讀 51,598評論 1 305
  • 那天,我揣著相機與錄音翻屈,去河邊找鬼陈哑。 笑死,一個胖子當著我的面吹牛伸眶,可吹牛的內容都是我干的惊窖。 我是一名探鬼主播,決...
    沈念sama閱讀 40,338評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼赚抡,長吁一口氣:“原來是場噩夢啊……” “哼爬坑!你這毒婦竟也來了?” 一聲冷哼從身側響起涂臣,我...
    開封第一講書人閱讀 39,249評論 0 276
  • 序言:老撾萬榮一對情侶失蹤盾计,失蹤者是張志新(化名)和其女友劉穎售担,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體署辉,經...
    沈念sama閱讀 45,696評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡族铆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,888評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了哭尝。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片哥攘。...
    茶點故事閱讀 40,013評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖材鹦,靈堂內的尸體忽然破棺而出逝淹,到底是詐尸還是另有隱情,我是刑警寧澤桶唐,帶...
    沈念sama閱讀 35,731評論 5 346
  • 正文 年R本政府宣布栅葡,位于F島的核電站,受9級特大地震影響尤泽,放射性物質發(fā)生泄漏欣簇。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,348評論 3 330
  • 文/蒙蒙 一坯约、第九天 我趴在偏房一處隱蔽的房頂上張望熊咽。 院中可真熱鬧,春花似錦闹丐、人聲如沸横殴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽滥玷。三九已至,卻和暖如春巍棱,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蛋欣。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評論 1 270
  • 我被黑心中介騙來泰國打工航徙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人陷虎。 一個月前我還...
    沈念sama閱讀 48,203評論 3 370
  • 正文 我出身青樓到踏,卻偏偏與公主長得像,于是被迫代替她去往敵國和親尚猿。 傳聞我的和親對象是個殘疾皇子窝稿,可洞房花燭夜當晚...
    茶點故事閱讀 44,960評論 2 355

推薦閱讀更多精彩內容