最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

快速入門Java中的Lambda表達(dá)式

 更新時(shí)間:2016年08月12日 09:36:25   投稿:daisy  
Lambda作為函數(shù)式編程中的基礎(chǔ)部分,在其他編程語(yǔ)言中早就廣為使用,但在Java領(lǐng)域中發(fā)展較慢,直到j(luò)ava8,才開(kāi)始支持Lambda。網(wǎng)上關(guān)于Lambda的教程很多,今天小編給大家分享一篇快速入手Lambda的教程。

Lambda簡(jiǎn)介

Lambda表達(dá)式是Java SE 8中一個(gè)重要的新特性。lambda表達(dá)式允許你通過(guò)表達(dá)式來(lái)代替功能接口。 lambda表達(dá)式就和方法一樣,它提供了一個(gè)正常的參數(shù)列表和一個(gè)使用這些參數(shù)的主體(body,可以是一個(gè)表達(dá)式或一個(gè)代碼塊)。

Lambda表達(dá)式還增強(qiáng)了集合庫(kù)。 Java SE 8添加了2個(gè)對(duì)集合數(shù)據(jù)進(jìn)行批量操作的包: java.util.function 包以及 java.util.stream 包。 流(stream)就如同迭代器(iterator),但附加了許多額外的功能。 總的來(lái)說(shuō),lambda表達(dá)式和 stream 是自Java語(yǔ)言添加泛型(Generics)和注解(annotation)以來(lái)最大的變化。

Lambda表達(dá)式本質(zhì)上是匿名方法,其底層還是通過(guò)invokedynamic指令來(lái)生成匿名類來(lái)實(shí)現(xiàn)。它提供了更為簡(jiǎn)單的語(yǔ)法和寫作方式,允許你通過(guò)表達(dá)式來(lái)代替函數(shù)式接口。在一些人看來(lái),Lambda就是可以讓你的代碼變得更簡(jiǎn)潔,完全可以不使用——這種看法當(dāng)然沒(méi)問(wèn)題,但重要的是lambda為Java帶來(lái)了閉包。得益于Lamdba對(duì)集合的支持,通過(guò)Lambda在多核處理器條件下對(duì)集合遍歷時(shí)的性能提高極大,另外我們可以以數(shù)據(jù)流的方式處理集合——這是非常有吸引力的。

Lambda語(yǔ)法

Lambda的語(yǔ)法極為簡(jiǎn)單,類似如下結(jié)構(gòu):

(parameters) -> expression

或者

(parameters) -> { statements; }

Lambda表達(dá)式由三部分組成:

      1、paramaters:類似方法中的形參列表,這里的參數(shù)是函數(shù)式接口里的參數(shù)。這里的參數(shù)類型可以明確的聲明也可不聲明而由JVM隱含的推斷。另外當(dāng)只有一個(gè)推斷類型時(shí)可以省略掉圓括號(hào)。

      2、->:可理解為“被用于”的意思

      3、方法體:可以是表達(dá)式也可以代碼塊,是函數(shù)式接口里方法的實(shí)現(xiàn)。代碼塊可返回一個(gè)值或者什么都不反回,這里的代碼塊塊等同于方法的方法體。如果是表達(dá)式,也可以返回一個(gè)值或者什么都不反回。

我們通過(guò)以下幾個(gè)示例來(lái)做說(shuō)明:

//示例1:不需要接受參數(shù),直接返回10
()->10

//示例2:接受兩個(gè)int類型的參數(shù),并返回這兩個(gè)參數(shù)相加的和
(int x,int y)->x+y;

//示例2:接受x,y兩個(gè)參數(shù),該參數(shù)的類型由JVM根據(jù)上下文推斷出來(lái),并返回兩個(gè)參數(shù)的和
(x,y)->x+y;

//示例3:接受一個(gè)字符串,并將該字符串打印到控制到,不反回結(jié)果
(String name)->System.out.println(name);

//示例4:接受一個(gè)推斷類型的參數(shù)name,并將該字符串打印到控制臺(tái)
name->System.out.println(name);

//示例5:接受兩個(gè)String類型參數(shù),并分別輸出,不反回
(String name,String sex)->{System.out.println(name);System.out.println(sex)}

//示例6:接受一個(gè)參數(shù)x,并返回該該參數(shù)的兩倍
x->2*x

Lambda用在哪里

在[函數(shù)式接口][1]中我們知道Lambda表達(dá)式的目標(biāo)類型是函數(shù)性接口——每一個(gè)Lambda都能通過(guò)一個(gè)特定的函數(shù)式接口與一個(gè)給定的類型進(jìn)行匹配。因此一個(gè)Lambda表達(dá)式能被應(yīng)用在與其目標(biāo)類型匹配的任何地方,lambda表達(dá)式必須和函數(shù)式接口的抽象函數(shù)描述一樣的參數(shù)類型,它的返回類型也必須和抽象函數(shù)的返回類型兼容,并且他能拋出的異常也僅限于在函數(shù)的描述范圍中。

接下來(lái),我們看一個(gè)自定義的函數(shù)式接口示例:

 @FunctionalInterface
 interface Converter<F, T>{

   T convert(F from);

}

首先用傳統(tǒng)的方式來(lái)使用該接口:

 Converter<String ,Integer> converter=new Converter<String, Integer>() {
      @Override
      public Integer convert(String from) {
        return Integer.valueOf(from);
      }
    };

    Integer result = converter.convert("200");
    System.out.println(result);

很顯然這沒(méi)任何問(wèn)題,那么接下里就是Lambda上場(chǎng)的時(shí)刻,用Lambda實(shí)現(xiàn)Converter接口:

Converter<String ,Integer> converter=(param) -> Integer.valueOf(param);
    Integer result = converter.convert("101");
    System.out.println(result);

通過(guò)上例,我想你已經(jīng)對(duì)Lambda的使用有了個(gè)簡(jiǎn)單的認(rèn)識(shí),下面,我們?cè)谟靡粋€(gè)常用的Runnable做演示:

在以前我們可能會(huì)寫下這種代碼:

new Thread(new Runnable() {
      @Override
      public void run() {
        System.out.println("hello lambda");
      }
    }).start();

在某些情況下,大量的匿名類會(huì)讓代碼顯得雜亂無(wú)章?,F(xiàn)在可以用Lambda來(lái)使它變得簡(jiǎn)潔:

new Thread(() -> System.out.println("hello lambda")).start();

方法引用

方法引用是Lambda表達(dá)式的一個(gè)簡(jiǎn)化寫法。所引用的方法其實(shí)是Lambda表達(dá)式的方法體的實(shí)現(xiàn),其語(yǔ)法結(jié)構(gòu)為:

ObjectRef::methodName

左邊可以是類名或者實(shí)例名,中間是方法引用符號(hào)”::”,右邊是相應(yīng)的方法名。

方法引用被分為三類:

1. 靜態(tài)方法引用

在某些情況下,我們可能寫出這樣的代碼:

public class ReferenceTest {
  public static void main(String[] args) {
    Converter<String ,Integer> converter=new Converter<String, Integer>() {
      @Override
      public Integer convert(String from) {
        return ReferenceTest.String2Int(from);
      }
    };
    converter.convert("120");

  }

  @FunctionalInterface
  interface Converter<F,T>{
    T convert(F from);
  }

  static int String2Int(String from) {
    return Integer.valueOf(from);
  }
}

這時(shí)候如果用靜態(tài)引用會(huì)使的代碼更加簡(jiǎn)潔:

 Converter<String, Integer> converter = ReferenceTest::String2Int;
 converter.convert("120");

2. 實(shí)例方法引用

我們也可能會(huì)寫下這樣的代碼:

public class ReferenceTest {
  public static void main(String[] args) {

    Converter<String, Integer> converter = new Converter<String, Integer>() {
      @Override
      public Integer convert(String from) {
        return new Helper().String2Int(from);
      }
    };
    converter.convert("120");
  }

  @FunctionalInterface
  interface Converter<F, T> {
    T convert(F from);
  }

  static class Helper {
    public int String2Int(String from) {
      return Integer.valueOf(from);
    }
  }
}

同樣用實(shí)例方法引用會(huì)顯得更加簡(jiǎn)潔:

 Helper helper = new Helper();
 Converter<String, Integer> converter = helper::String2Int;
 converter.convert("120");

3. 構(gòu)造方法引用

現(xiàn)在我們來(lái)演示構(gòu)造方法的引用。首先我們定義一個(gè)父類Animal:

  class Animal{
    private String name;
    private int age;

    public Animal(String name, int age) {
      this.name = name;
      this.age = age;
    }

    public void behavior(){

    }
  }

接下來(lái),我們?cè)诙x兩個(gè)Animal的子類:Dog、Bird

public class Bird extends Animal {

  public Bird(String name, int age) {
    super(name, age);
  }

  @Override
  public void behavior() {
    System.out.println("fly");
  }
}

class Dog extends Animal {

  public Dog(String name, int age) {
    super(name, age);
  }

  @Override
  public void behavior() {
    System.out.println("run");
  }
}

隨后我們定義工廠接口:

  interface Factory<T extends Animal> {
    T create(String name, int age);
  }

接下來(lái)我們還是用傳統(tǒng)的方法來(lái)創(chuàng)建Dog類和Bird類的對(duì)象:

    Factory factory=new Factory() {
      @Override
      public Animal create(String name, int age) {
        return new Dog(name,age);
      }
    };
    factory.create("alias", 3);
    factory=new Factory() {
      @Override
      public Animal create(String name, int age) {
        return new Bird(name,age);
      }
    };
    factory.create("smook", 2);

僅僅為了創(chuàng)建兩個(gè)對(duì)象就寫了十多號(hào)代碼,現(xiàn)在我們用構(gòu)造函數(shù)引用試試:

 Factory<Animal> dogFactory =Dog::new;
 Animal dog = dogFactory.create("alias", 4);

 Factory<Bird> birdFactory = Bird::new;
 Bird bird = birdFactory.create("smook", 3);

這樣代碼就顯得干凈利落了。通過(guò)Dog::new這種方式來(lái)穿件對(duì)象時(shí),Factory.create函數(shù)的簽名選擇相應(yīng)的造函數(shù)。

Lambda的域以及訪問(wèn)限制

域即作用域,Lambda表達(dá)式中的參數(shù)列表中的參數(shù)在該Lambda表達(dá)式范圍內(nèi)(域)有效。在作用Lambda表達(dá)式內(nèi),可以訪問(wèn)外部的變量:局部變量、類變量和靜態(tài)變量,但操作受限程度不一。

訪問(wèn)局部變量

在Lambda表達(dá)式外部的局部變量會(huì)被JVM隱式的編譯成final類型,因此只能訪問(wèn)外而不能修改。

public class ReferenceTest {
  public static void main(String[] args) {

    int n = 3;
    Calculate calculate = param -> {
      //n=10; 編譯錯(cuò)誤
      return n + param;
    };
    calculate.calculate(10);
  }

  @FunctionalInterface
  interface Calculate {
    int calculate(int value);
  }

}

訪問(wèn)靜態(tài)變量和成員變量

在Lambda表達(dá)式內(nèi)部,對(duì)靜態(tài)變量和成員變量可讀可寫。

public class ReferenceTest {
  public int count = 1;
  public static int num = 2;

  public void test() {
    Calculate calculate = param -> {
      num = 10;//修改靜態(tài)變量
      count = 3;//修改成員變量
      return n + param;
    };
    calculate.calculate(10);
  }

  public static void main(String[] args) {

  }

  @FunctionalInterface
  interface Calculate {
    int calculate(int value);
  }

}

Lambda不能訪問(wèn)函數(shù)接口的默認(rèn)方法

java8增強(qiáng)了接口,其中包括接口可添加default關(guān)鍵詞定義的默認(rèn)方法,這里我們需要注意,Lambda表達(dá)式內(nèi)部不支持訪問(wèn)默認(rèn)方法。

Lambda實(shí)踐

在[函數(shù)式接口][2]一節(jié)中,我們提到java.util.function包中內(nèi)置許多函數(shù)式接口,現(xiàn)在將對(duì)常用的函數(shù)式接口做說(shuō)明。

Predicate接口

輸入一個(gè)參數(shù),并返回一個(gè)Boolean值,其中內(nèi)置許多用于邏輯判斷的默認(rèn)方法:

  @Test
  public void predicateTest() {
    Predicate<String> predicate = (s) -> s.length() > 0;
    boolean test = predicate.test("test");
    System.out.println("字符串長(zhǎng)度大于0:" + test);

    test = predicate.test("");
    System.out.println("字符串長(zhǎng)度大于0:" + test);

    test = predicate.negate().test("");
    System.out.println("字符串長(zhǎng)度小于0:" + test);

    Predicate<Object> pre = Objects::nonNull;
    Object ob = null;
    test = pre.test(ob);
    System.out.println("對(duì)象不為空:" + test);
    ob = new Object();
    test = pre.test(ob);
    System.out.println("對(duì)象不為空:" + test);
  }

Function接口

接收一個(gè)參數(shù),返回單一的結(jié)果,默認(rèn)的方法(andThen)可將多個(gè)函數(shù)串在一起,形成復(fù)合Funtion(有輸入,有輸出)結(jié)果,

  @Test
  public void functionTest() {
    Function<String, Integer> toInteger = Integer::valueOf;
    //toInteger的執(zhí)行結(jié)果作為第二個(gè)backToString的輸入
    Function<String, String> backToString = toInteger.andThen(String::valueOf);
    String result = backToString.apply("1234");
    System.out.println(result);

    Function<Integer, Integer> add = (i) -> {
      System.out.println("frist input:" + i);
      return i * 2;
    };
    Function<Integer, Integer> zero = add.andThen((i) -> {
      System.out.println("second input:" + i);
      return i * 0;
    });

    Integer res = zero.apply(8);
    System.out.println(res);
  }

Supplier接口

返回一個(gè)給定類型的結(jié)果,與Function不同的是,Supplier不需要接受參數(shù)(供應(yīng)者,有輸出無(wú)輸入)

  @Test
  public void supplierTest() {
    Supplier<String> supplier = () -> "special type value";
    String s = supplier.get();
    System.out.println(s);
  }

Consumer接口

代表了在單一的輸入?yún)?shù)上需要進(jìn)行的操作。和Function不同的是,Consumer沒(méi)有返回值(消費(fèi)者,有輸入,無(wú)輸出)

  @Test
  public void consumerTest() {
    Consumer<Integer> add5 = (p) -> {
      System.out.println("old value:" + p);
      p = p + 5;
      System.out.println("new value:" + p);
    };
    add5.accept(10);
  }

以上四個(gè)接口的用法代表了java.util.function包中四種類型,理解這四個(gè)函數(shù)式接口之后,其他的接口也就容易理解了,現(xiàn)在我們來(lái)做一下簡(jiǎn)單的總結(jié):

Predicate用來(lái)邏輯判斷,Function用在有輸入有輸出的地方,Supplier用在無(wú)輸入,有輸出的地方,而Consumer用在有輸入,無(wú)輸出的地方。你大可通過(guò)其名稱的含義來(lái)獲知其使用場(chǎng)景。

Stream

Lambda為java8帶了閉包,這一特性在集合操作中尤為重要:java8中支持對(duì)集合對(duì)象的stream進(jìn)行函數(shù)式操作,此外,stream api也被集成進(jìn)了collection api,允許對(duì)集合對(duì)象進(jìn)行批量操作。

下面我們來(lái)認(rèn)識(shí)Stream。

Stream表示數(shù)據(jù)流,它沒(méi)有數(shù)據(jù)結(jié)構(gòu),本身也不存儲(chǔ)元素,其操作也不會(huì)改變?cè)碨tream,而是生成新Stream.作為一種操作數(shù)據(jù)的接口,它提供了過(guò)濾、排序、映射、規(guī)約等多種操作方法,這些方法按照返回類型被分為兩類:凡是返回Stream類型的方法,稱之為中間方法(中間操作),其余的都是完結(jié)方法(完結(jié)操作)。完結(jié)方法返回一個(gè)某種類型的值,而中間方法則返回新的Stream。中間方法的調(diào)用通常是鏈?zhǔn)降?,該過(guò)程會(huì)形成一個(gè)管道,當(dāng)完結(jié)方法被調(diào)用時(shí)會(huì)導(dǎo)致立即從管道中消費(fèi)值,這里我們要記住:Stream的操作盡可能以“延遲”的方式運(yùn)行,也就是我們常說(shuō)的“懶操作”,這樣有助于減少資源占用,提高性能。對(duì)于所有的中間操作(除sorted外)都是運(yùn)行在延遲模式下。

Stream不但提供了強(qiáng)大的數(shù)據(jù)操作能力,更重要的是Stream既支持串行也支持并行,并行使得Stream在多核處理器上有著更好的性能。

Stream的使用過(guò)程有著固定的模式:

      1、創(chuàng)建Stream

      2、通過(guò)中間操作,對(duì)原始Stream進(jìn)行“變化”并生成新的Stream

      3、使用完結(jié)操作,生成最終結(jié)果

也就是

      創(chuàng)建——>變化——>完結(jié)

Stream的創(chuàng)建

對(duì)于集合來(lái)說(shuō),可以通過(guò)調(diào)用集合的stream()或者parallelStream()來(lái)創(chuàng)建,另外這兩個(gè)方法也在Collection接口中實(shí)現(xiàn)了。對(duì)于數(shù)組來(lái)說(shuō),可以通過(guò)Stream的靜態(tài)方法of(T … values)來(lái)創(chuàng)建,另外,Arrays也提供了有關(guān)stream的支持。

除了以上基于集合或者數(shù)組來(lái)創(chuàng)建Stream,也可以通過(guò)Steam.empty()創(chuàng)建空的Stream,或者利用Stream的generate()來(lái)創(chuàng)建無(wú)窮的Stream。

下面我們以串行Stream為例,分別說(shuō)明Stream幾種常用的中間方法和完結(jié)方法。首先創(chuàng)建一個(gè)List集合:

List<String> lists=new ArrayList<String >();
    lists.add("a1");
    lists.add("a2");
    lists.add("b1");
    lists.add("b2");
    lists.add("b3");
    lists.add("o1");

中間方法

過(guò)濾器(Filter)

結(jié)合Predicate接口,F(xiàn)ilter對(duì)流對(duì)象中的所有元素進(jìn)行過(guò)濾,該操作是一個(gè)中間操作,這意味著你可以在操作返回結(jié)果的基礎(chǔ)上進(jìn)行其他操作。

  public static void streamFilterTest() {
    lists.stream().filter((s -> s.startsWith("a"))).forEach(System.out::println);

    //等價(jià)于以上操作
    Predicate<String> predicate = (s) -> s.startsWith("a");
    lists.stream().filter(predicate).forEach(System.out::println);

    //連續(xù)過(guò)濾
    Predicate<String> predicate1 = (s -> s.endsWith("1"));
    lists.stream().filter(predicate).filter(predicate1).forEach(System.out::println);
  }

排序(Sorted)

結(jié)合Comparator接口,該操作返回一個(gè)排序過(guò)后的流的視圖,原始流的順序不會(huì)改變。通過(guò)Comparator來(lái)指定排序規(guī)則,默認(rèn)是按照自然順序排序。

   public static void streamSortedTest() {
    System.out.println("默認(rèn)Comparator");
    lists.stream().sorted().filter((s -> s.startsWith("a"))).forEach(System.out::println);

    System.out.println("自定義Comparator");
    lists.stream().sorted((p1, p2) -> p2.compareTo(p1)).filter((s -> s.startsWith("a"))).forEach(System.out::println);

  }

映射(Map)

結(jié)合Function接口,該操作能將流對(duì)象中的每個(gè)元素映射為另一種元素,實(shí)現(xiàn)元素類型的轉(zhuǎn)換。

  public static void streamMapTest() {
    lists.stream().map(String::toUpperCase).sorted((a, b) -> b.compareTo(a)).forEach(System.out::println);

    System.out.println("自定義映射規(guī)則");
    Function<String, String> function = (p) -> {
      return p + ".txt";
    };
    lists.stream().map(String::toUpperCase).map(function).sorted((a, b) -> b.compareTo(a)).forEach(System.out::println);

  }

在上面簡(jiǎn)單介紹了三種常用的操作,這三種操作極大簡(jiǎn)化了集合的處理。接下來(lái),介紹幾種完結(jié)方法:

完結(jié)方法

“變換”過(guò)程之后,需要獲取結(jié)果,即完成操作。下面我們來(lái)看相關(guān)的操作:

匹配(Match)

用來(lái)判斷某個(gè)predicate是否和流對(duì)象相匹配,最終返回Boolean類型結(jié)果,例如:

  public static void streamMatchTest() {
    //流對(duì)象中只要有一個(gè)元素匹配就返回true
    boolean anyStartWithA = lists.stream().anyMatch((s -> s.startsWith("a")));
    System.out.println(anyStartWithA);
    //流對(duì)象中每個(gè)元素都匹配就返回true
    boolean allStartWithA
        = lists.stream().allMatch((s -> s.startsWith("a")));
    System.out.println(allStartWithA);
  }

收集(Collect)

在對(duì)經(jīng)過(guò)變換之后,我們將變換的Stream的元素收集,比如將這些元素存至集合中,此時(shí)便可以使用Stream提供的collect方法,例如:

  public static void streamCollectTest() {
    List<String> list = lists.stream().filter((p) -> p.startsWith("a")).sorted().collect(Collectors.toList());
    System.out.println(list);

  }

計(jì)數(shù)(Count)

類似sql的count,用來(lái)統(tǒng)計(jì)流中元素的總數(shù),例如:

  public static void streamCountTest() {
    long count = lists.stream().filter((s -> s.startsWith("a"))).count();
    System.out.println(count);
  }

規(guī)約(Reduce)

reduce方法允許我們用自己的方式去計(jì)算元素或者將一個(gè)Stream中的元素以某種規(guī)律關(guān)聯(lián),例如:

  public static void streamReduceTest() {
    Optional<String> optional = lists.stream().sorted().reduce((s1, s2) -> {
      System.out.println(s1 + "|" + s2);
      return s1 + "|" + s2;
    });
  }

執(zhí)行結(jié)果如下:

a1|a2
a1|a2|b1
a1|a2|b1|b2
a1|a2|b1|b2|b3
a1|a2|b1|b2|b3|o1

并行Stream VS 串行Stream

到目前我們已經(jīng)將常用的中間操作和完結(jié)操作介紹完了。當(dāng)然所有的的示例都是基于串行Stream。接下來(lái)介紹重點(diǎn)戲——并行Stream(parallel Stream)。并行Stream基于Fork-join并行分解框架實(shí)現(xiàn),將大數(shù)據(jù)集合切分為多個(gè)小數(shù)據(jù)結(jié)合交給不同的線程去處理,這樣在多核處理情況下,性能會(huì)得到很大的提高。這和MapReduce的設(shè)計(jì)理念一致:大任務(wù)化小,小任務(wù)再分配到不同的機(jī)器執(zhí)行。只不過(guò)這里的小任務(wù)是交給不同的處理器。

通過(guò)parallelStream()創(chuàng)建并行Stream。為了驗(yàn)證并行Stream是否真的能提高性能,我們執(zhí)行以下測(cè)試代碼:

首先創(chuàng)建一個(gè)較大的集合:

  List<String> bigLists = new ArrayList<>();
    for (int i = 0; i < 10000000; i++) {
      UUID uuid = UUID.randomUUID();
      bigLists.add(uuid.toString());
    }

測(cè)試串行流下排序所用的時(shí)間:

  private static void notParallelStreamSortedTest(List<String> bigLists) {
    long startTime = System.nanoTime();
    long count = bigLists.stream().sorted().count();
    long endTime = System.nanoTime();
    long millis = TimeUnit.NANOSECONDS.toMillis(endTime - startTime);
    System.out.println(System.out.printf("串行排序: %d ms", millis));

  }

測(cè)試并行流下排序所用的時(shí)間:

  private static void parallelStreamSortedTest(List<String> bigLists) {
    long startTime = System.nanoTime();
    long count = bigLists.parallelStream().sorted().count();
    long endTime = System.nanoTime();
    long millis = TimeUnit.NANOSECONDS.toMillis(endTime - startTime);
    System.out.println(System.out.printf("并行排序: %d ms", millis));

  }

結(jié)果如下:

          串行排序: 13336 ms
          并行排序: 6755 ms

看到這里,我們確實(shí)發(fā)現(xiàn)性能提高了約么50%,你也可能會(huì)想以后都用parallel Stream不久行了么?實(shí)則不然,如果你現(xiàn)在還是單核處理器,而數(shù)據(jù)量又不算很大的情況下,串行流仍然是這種不錯(cuò)的選擇。你也會(huì)發(fā)現(xiàn)在某些情況,串行流的性能反而更好,至于具體的使用,需要你根據(jù)實(shí)際場(chǎng)景先測(cè)試后再?zèng)Q定。

懶操作

上面我們談到Stream盡可能以延遲的方式運(yùn)行,這里通過(guò)創(chuàng)建一個(gè)無(wú)窮大的Stream來(lái)說(shuō)明:

首先通過(guò)Stream的generate方法來(lái)一個(gè)自然數(shù)序列,然后通過(guò)map變換Stream:

 //遞增序列
 class NatureSeq implements Supplier<Long> {
    long value = 0;

    @Override
    public Long get() {
      value++;
      return value;
    }
  }

 public void streamCreateTest() {
    Stream<Long> stream = Stream.generate(new NatureSeq());
    System.out.println("元素個(gè)數(shù):"+stream.map((param) -> {
      return param;
    }).limit(1000).count());

  }

執(zhí)行結(jié)果為:

       元素個(gè)數(shù):1000

我們發(fā)現(xiàn)開(kāi)始時(shí)對(duì)這個(gè)無(wú)窮大的Stream做任何中間操作(如:filter,map等,但sorted不行)都是可以的,也就是對(duì)Stream進(jìn)行中間操作并生存一個(gè)新的Stream的過(guò)程并非立刻生效的(不然此例中的map操作會(huì)永遠(yuǎn)的運(yùn)行下去,被阻塞?。?,當(dāng)遇到完結(jié)方法時(shí)stream才開(kāi)始計(jì)算。通過(guò)limit()方法,把這個(gè)無(wú)窮的Stream轉(zhuǎn)為有窮的Stream。

總結(jié)

以上就是Java Lambda快速入門詳解的全部?jī)?nèi)容,看完本文后大家是不是對(duì)Java Lambda有了更深的了解,希望本文對(duì)大家學(xué)習(xí)Java Lambda能有所幫助。

相關(guān)文章

  • idea項(xiàng)目debug模式無(wú)法啟動(dòng)的解決

    idea項(xiàng)目debug模式無(wú)法啟動(dòng)的解決

    這篇文章主要介紹了idea項(xiàng)目debug模式無(wú)法啟動(dòng)的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-02-02
  • Java實(shí)現(xiàn)單向鏈表反轉(zhuǎn)

    Java實(shí)現(xiàn)單向鏈表反轉(zhuǎn)

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)單向鏈表反轉(zhuǎn),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • java根據(jù)開(kāi)始時(shí)間結(jié)束時(shí)間計(jì)算中間間隔日期的實(shí)例代碼

    java根據(jù)開(kāi)始時(shí)間結(jié)束時(shí)間計(jì)算中間間隔日期的實(shí)例代碼

    這篇文章主要介紹了java根據(jù)開(kāi)始時(shí)間結(jié)束時(shí)間計(jì)算中間間隔日期的實(shí)例代碼,需要的朋友可以參考下
    2019-05-05
  • Mybatis中特殊SQL的執(zhí)行

    Mybatis中特殊SQL的執(zhí)行

    這篇文章主要介紹了Mybatis中特殊SQL的執(zhí)行,介紹內(nèi)容包括模糊查詢、批量刪除、動(dòng)態(tài)設(shè)置表名、添加功能獲取自增的主鍵等相關(guān)資料,需要的小伙伴可以參考一下
    2022-04-04
  • Spring Boot 靜態(tài)資源處理

    Spring Boot 靜態(tài)資源處理

    今天小編就為大家分享一篇關(guān)于Spring Boot 靜態(tài)資源處理,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-12-12
  • 基于Jasypt對(duì)SpringBoot配置文件加密

    基于Jasypt對(duì)SpringBoot配置文件加密

    這篇文章主要介紹了基于Jasypt對(duì)SpringBoot配置文件加密,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • Java并發(fā)系列之CountDownLatch源碼分析

    Java并發(fā)系列之CountDownLatch源碼分析

    這篇文章主要為大家詳細(xì)介紹了Java并發(fā)系列之CountDownLatch源碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-03-03
  • 程序包org.springframework不存在的解決辦法

    程序包org.springframework不存在的解決辦法

    這篇文章主要介紹了程序包org.springframework不存在的解決辦法,在使用IDEA創(chuàng)建SpringBoot項(xiàng)目時(shí),剛打開(kāi)無(wú)法正常運(yùn)行,本文通過(guò)圖文結(jié)合的方式給大家介紹的非常詳細(xì),具有一定參考價(jià)值,需要的朋友可以參考下
    2024-07-07
  • Kotlin this詳解及實(shí)例

    Kotlin this詳解及實(shí)例

    這篇文章主要介紹了Kotlin this詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下
    2017-06-06
  • Java?垃圾回收超詳細(xì)講解記憶集和卡表

    Java?垃圾回收超詳細(xì)講解記憶集和卡表

    卡表就是記憶集的一種具體實(shí)現(xiàn),它定義了記憶集的記錄精度、與堆內(nèi)存的映射關(guān)系等。?關(guān)于卡表與記憶集的關(guān)系,不妨按照J(rèn)ava語(yǔ)言中HashMap與Map的關(guān)系來(lái)類比理解。記憶集是一種用于記錄從非收集區(qū)域指向收集區(qū)域的指針集合的抽象數(shù)據(jù)結(jié)構(gòu)
    2022-04-04

最新評(píng)論

包头市| 浑源县| 皋兰县| 汉源县| 余江县| 东安县| 天气| 玉树县| 遂溪县| 淳安县| 绥芬河市| 万安县| 阿城市| 宁武县| 扬州市| 从化市| 法库县| 屏南县| 罗源县| 准格尔旗| 纳雍县| 博湖县| 星子县| 乌鲁木齐县| 象山县| 汕头市| 寿宁县| 达日县| 分宜县| 云龙县| 罗山县| 达拉特旗| 当涂县| 钦州市| 莱阳市| 顺义区| 肇源县| 宣城市| 永州市| 璧山县| 榆树市|