JDK1.8新特性 Lambda使用 (二)

Lambda表達式是Java SE 8中一個重要的新特性。lambda表達式允許你通過表達式來代替功能接口。 lambda表達式就和方法一樣,它提供了一個正常的參數列表和一個使用這些參數的主體(body,可以是一個表達式或一個代碼塊)。
Lambda表達式還增強了集合庫。 Java SE 8添加了2個對集合數據進行批量操作的包: java.util.function 包以及java.util.stream 包。 流(stream)就如同迭代器(iterator),但附加了許多額外的功能。 總的來說,lambda表達式和 stream 是自Java語言添加泛型(Generics)和註解(annotation)以來最大的變化。 在本文中,我們將從簡單到複雜的示例中見認識lambda表達式和stream的強悍。

Lambda表達式本質是匿名方法,下面是一些lambda表達式:
(int x, int y) -> x + y
() -> 42
(String s) -> { System.out.println(s); }

第一個lambda表達式接收x和y這兩個整形參數並返回它們的和;
第二個lambda表達式不接收參數,返回整數42;
第三個lambda表達式接收一個字符串並把它打印到控制檯,不返回值。

lambda表達式的語法由參數列表、箭頭符號->和函數體組成。函數體既可以是一個表達式,也可以是一個語句塊:
表達式:表達式會被執行然後返回執行結果。
語句塊:語句塊中的語句會被依次執行,就像方法中的語句一樣。
return語句會把控制權交給匿名方法的調用者
break和continue只能在循環中使用
如果函數體有返回值,那麼函數體內部的每一條路徑都必須返回值

1、ArrayList的使用

Integer[] numArray={1,2,3,4,5,6,7,8};
List<Integer> nameList= Arrays.asList(numArray);

/******************1、使用舊的方式進行循環輸出************************************/
for (int num:nameList){
    System.out.println(num);
}

System.out.println("*******************************************************華麗的分割線");

/******************2、如果使用一行代碼,使用以下這種方式***************************/
nameList.forEach((num)->System.out.println(num));

System.out.println("*******************************************************華麗的分割線");

/******************3、如果寫入多行代碼使用以下這種方式****************************/
nameList.forEach((num)->{
    System.out.println(num);
});

System.out.println("*******************************************************華麗的分割線");

/*******************4、使用雙冒號操作符*****************************************/
nameList.forEach(System.out::println);

2、Function的使用

Function<Integer, Integer> name = e -> e * 2;

Function<Integer, Integer> square = e -> e * e;

int value = name.andThen(square).apply(3);

3、Runnable(線程)的使用

/******************1、使用匿名內部類************************************/
new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello world!");
    }
}.run();
/******************2、使用Lambda 表達式************************************/
Runnable runnable=()->System.out.println("Hello world!");

4、Thread(線程)的使用

 /******************1、使用匿名內部類************************************/
 new Thread(new Runnable() {
     @Override
     public void run() {
         System.out.println("Hello world !");
     }
 }).start();
 /******************2、使用Lambda 表達式********************************/
 int i=1;
 new Thread(()->System.out.println("Hello world !")).start();

5、Sort的使用

/******************1、正常情況下使用排序************************************/
String[] players = {"Rafael Nadal", "Novak Djokovic",
        "Stanislas Wawrinka", "David Ferrer",
        "Roger Federer", "Andy Murray",
        "Tomas Berdych", "Juan Martin Del Potro",
        "Richard Gasquet", "John Isner"};
Arrays.sort(players, new Comparator<String>() {
    @Override
    public int compare(String s1, String s2) {
        return (s1.compareTo(s2));
    }
});
Arrays.asList(players).forEach(System.out::println);

/******************2、使用Lambda 表達式************************************/
/*********(1)、第一種方式************/
Comparator<String> comparator=(String s1,String s2)->(s1.compareTo(s2));
Arrays.sort(players,comparator);
Arrays.asList(players).forEach(System.out::println);
/*********(1)、第二種方式************/
Arrays.sort(players,(String s1,String s2)->(s1.compareTo(s2)));
Arrays.asList(players).forEach(System.out::println);

6、Stream的使用

public class Person {
    private String firstName, lastName, job, gender;
    private int salary, age;
    public Person(String firstName, String lastName, String job,
                  String gender, int age, int salary)       {
        this.firstName = firstName;
        this.lastName = lastName;
        this.gender = gender;
        this.age = age;
        this.job = job;
        this.salary = salary;
    }

    public Person() {
    }
    public Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public int getSalary() {
        return salary;
    }

    public void setSalary(int salary) {
        this.salary = salary;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

(1)、使用filter

/********************使用filter*********************/
Jdk_8_Streams_filter jdk_8_Streams=new Jdk_8_Streams_filter();
System.out.println("下面是月薪超過 $1,400 的PHP程序員:");
jdk_8_Streams.phpProgrammers.stream()
        .filter((p) -> (p.getSalary() > 1400))
        .forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));

(2)、使用predicate

/********************數據斷言predicate(類似於js當中Es6語法當中的匿名函數)*********************/
Jdk_8_Streams_Predicate jdk_8_Streams=new Jdk_8_Streams_Predicate();

Predicate<Person> ageFilter = (p) -> (p.getAge() > 25);
Predicate<Person> salaryFilter = (p) -> (p.getSalary() > 1400);
Predicate<Person> genderFilter = (p) -> ("female".equals(p.getGender()));
System.out.println("下面是年齡大於24歲且月薪在$1,400以上的女PHP程序員:");
jdk_8_Streams.phpProgrammers.stream()
        .filter(ageFilter)
        .filter(salaryFilter)
        .filter(genderFilter)
        .forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));

(3)、使用limit

/********************數量限制*********************/
Jdk_8_Streams_Limit jdk_8_Streams=new Jdk_8_Streams_Limit();

jdk_8_Streams.javaProgrammers.stream()
        .limit(3)
        .forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));

(4)、排序(sorted)

/********************排序*********************/
Jdk_8_Streams_Sort jdk_8_Streams=new Jdk_8_Streams_Sort();
List<Person> sortedJavaProgrammers = jdk_8_Streams.javaProgrammers
       .stream()
       .sorted((p1,p2)->{
           if(p1.getAge()==p2.getAge()){
               return p1.getFirstName().compareTo(p2.getFirstName());
           }else {
               return Integer.valueOf(p1.getAge()).compareTo(Integer.valueOf(p2.getAge()));
           }
       })
       .limit(5)
       .collect(toList());
sortedJavaProgrammers.forEach((p) -> System.out.printf("%s %s; %n", p.getFirstName(), p.getLastName()));

(5)、使用min()

/********************獲得最小值*********************/
Jdk_8_Streams_Min jdk_8_Streams=new Jdk_8_Streams_Min();

System.out.println("工資最低的 Java programmer:");
Person pers = jdk_8_Streams.javaProgrammers
        .stream()
        .min((p1, p2) -> (p1.getSalary() - p2.getSalary()))
        .get();

System.out.printf("Name: %s %s; Salary: $%,d.", pers.getFirstName(), pers.getLastName(), pers.getSalary());

(6)、使用max()

/********************獲得最大值*********************/
Jdk_8_Streams_Max jdk_8_Streams=new Jdk_8_Streams_Max();

System.out.println("工資最高的 Java programmer:");
Person person = jdk_8_Streams.javaProgrammers
        .stream()
        .max((p1, p2) -> (p1.getSalary() - p2.getSalary()))
        .get();
System.out.printf("Name: %s %s; Salary: $%,d.", person.getFirstName(), person.getLastName(), person.getSalary());

(7)、使用map()

final String[] waibu = {"lambda :"};
Jdk_8_Streams_Map.javaProgrammers.stream().map(item->{
   waibu[0]+=1;
   if(item.getSalary()>1900)
       return item;
   else
       return null;
}).filter(Objects::isNull).map(Person::getFirstName).forEach(System.out::println);

(8)、結合map(),使用set

/********************Set的使用*********************/
Jdk_8_Streams_Map_Set jdk_8_Streams=new Jdk_8_Streams_Map_Set();

Set<String> javaDevFirstName = jdk_8_Streams.javaProgrammers
        .stream()
        .map(Person::getFirstName)
        .collect(toSet());
javaDevFirstName.forEach(System.out::println);

(9)、結合map(),使用TreeSet

/********************TreeSet的使用*********************/
Jdk_8_Streams_Map_TreeSet jdk_8_Streams=new Jdk_8_Streams_Map_TreeSet();

TreeSet<String> javaDevLastName = jdk_8_Streams.javaProgrammers
        .stream()
        .map(Person::getLastName)
        .collect(toCollection(TreeSet::new));
for(Iterator iter = javaDevLastName.iterator(); iter.hasNext();) {
    System.out.println(iter.next());
}

(10)、結合map(),使用join()

/********************字符串連接*********************/
Jdk_8_Streams_Map_Join jdk_8_Streams=new Jdk_8_Streams_Map_Join();

String phpDevelopers = jdk_8_Streams.phpProgrammers
        .stream()
        .map(Person::getFirstName)
        .collect(joining(","));
System.out.println(phpDevelopers);

(11)、使用match

 /********************Match匹配*********************/
 Jdk_8_Streams_Match jdk_8_Streams=new Jdk_8_Streams_Match();
 boolean isExit=jdk_8_Streams.javaProgrammers.stream().anyMatch(p->p.getFirstName().startsWith("A"));
 System.out.println(isExit);

(12)、最終操作,使用規約(reduce)

 List<String> nameList= Arrays.asList("Tom","Brimen","Json","Ludn","Minmn");
 Optional<String> reduced =nameList
                 .stream()
                 .sorted()
                 .reduce((s1, s2) -> s1 + "," + s2);
 String aa=reduced.get();
 System.out.println(aa);
 reduced.ifPresent(System.out::println);

(13)、並行parallel

 /********************數據彙總*********************/
 Jdk_8_Streams_Parallel jdk_8_Streams=new Jdk_8_Streams_Parallel();
 int totalSalary=jdk_8_Streams.javaProgrammers.parallelStream().mapToInt(p->p.getSalary()).sum();
 System.out.println(totalSalary);

(14)、彙總統計數據

 List<Integer> numList= Arrays.asList(3,6,2,4,5,9);
 IntSummaryStatistics intSummaryStatistics=numList.stream().mapToInt(x->x).summaryStatistics();
 System.out.println("List當中的最大值:"+intSummaryStatistics.getMax());
 System.out.println("List當中的最小值:"+intSummaryStatistics.getMax());
 System.out.println("List當中的平均值:"+intSummaryStatistics.getAverage());
 System.out.println("List單中的總和:"+intSummaryStatistics.getSum());

7、使用Stream實現並行排序和串行排序

並行排序

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

 long t0 = System.nanoTime();
 long count = values.parallelStream().sorted().count();
 System.out.println(count);
 long t1 = System.nanoTime();
 long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
 System.out.println(String.format("parallel sort took: %d ms", millis));

串行排序

 int max = 1000000;
 List<String> values = new ArrayList<>(max);
 for (int i = 0; i < max; i++) {
     UUID uuid = UUID.randomUUID();
     values.add(uuid.toString());
 }
 long t0 = System.nanoTime();
 long count = values.stream().sorted().count();
 System.out.println(count);
 long t1 = System.nanoTime();
 long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
 System.out.println(String.format("sequential sort took: %d ms", millis));

總結:使用並行排序比串行排序要快的多,快50%左右。

8、map的使用

Map類型不支持stream,不過Map提供了一些新的有用的方法來處理一些日常任務。

 Map<Integer, String> map = new HashMap<>();
 for (int i = 0; i < 10; i++) {
     map.putIfAbsent(i, "val" + i);
 }

 map.computeIfPresent(3, (num, val) -> val + num);
 map.get(3);             // val33
 map.computeIfPresent(9, (num, val) -> null);
 map.containsKey(9);     // false
 map.computeIfAbsent(23, num -> "val" + num);
 map.containsKey(23);    // true
 map.computeIfAbsent(3, num -> "bam");
 map.get(3);             // val33

 map.remove(3, "val3");
 map.get(3);             // val33
 map.remove(3, "val33");
 map.get(3);             // null

 map.getOrDefault(42, "not found");  // not found

 map.merge(9, "val9", (value, newValue) -> value.concat(newValue));
 map.get(9);             // val9
 map.merge(9, "concat", (value, newValue) -> value.concat(newValue));
 map.get(9);             // val9concat
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章