⑴ 用Java 8 增加的 Stream API 能實現哪些優雅的演算法
Java 8引入了全新的Stream API。這里的Stream和I/O流不同,它更像具有Iterable的集合類,但行為和集合類又有所不同。
Stream API引入的目的在於彌補Java函數式編程的缺陷。對於很多支持函數式編程的語言,map()、rece()基本上都內置到語言的標准庫中了,不過,Java 8的Stream API總體來講仍然是非常完善和強大,足以用很少的代碼完成許多復雜的功能。
創建一個Stream有很多方法,最簡單的方法是把一個Collection變成Stream。我們來看最基本的幾個操作:
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Stream<Integer> stream = numbers.stream();
stream.filter((x) -> {
return x % 2 == 0;
}).map((x) -> {
return x * x;
}).forEach(System.out::println);
}
集合類新增的stream()方法用於把一個集合變成Stream,然後,通過filter()、map()等實現Stream的變換。Stream還有一個forEach()來完成每個元素的迭代。
為什麼不在集合類實現這些操作,而是定義了全新的Stream API?Oracle官方給出了幾個重要原因:
一是集合類持有的所有元素都是存儲在內存中的,非常巨大的集合類會佔用大量的內存,而Stream的元素卻是在訪問的時候才被計算出來,這種「延遲計算」的特性有點類似Clojure的lazy-seq,佔用內存很少。
二是集合類的迭代邏輯是調用者負責,通常是for循環,而Stream的迭代是隱含在對Stream的各種操作中,例如map()。
要理解「延遲計算」,不妨創建一個無窮大小的Stream。
如果要表示自然數集合,顯然用集合類是不可能實現的,因為自然數有無窮多個。但是Stream可以做到。
自然數集合的規則非常簡單,每個元素都是前一個元素的值+1,因此,自然數發生器用代碼實現如下:
class NaturalSupplier implements Supplier<Long> {
long value = 0;
public Long get() {
this.value = this.value + 1;
return this.value;
}
}
反復調用get(),將得到一個無窮數列,利用這個Supplier,可以創建一個無窮的Stream:
public static void main(String[] args) {
Stream<Long> natural = Stream.generate(new NaturalSupplier());
natural.map((x) -> {
return x * x;
}).limit(10).forEach(System.out::println);
}
對這個Stream做任何map()、filter()等操作都是完全可以的,這說明Stream API對Stream進行轉換並生成一個新的Stream並非實時計算,而是做了延遲計算。
當然,對這個無窮的Stream不能直接調用forEach(),這樣會無限列印下去。但是我們可以利用limit()變換,把這個無窮Stream變換為有限的Stream。
利用Stream API,可以設計更加簡單的數據介面。例如,生成斐波那契數列,完全可以用一個無窮流表示(受限Java的long型大小,可以改為BigInteger):
class FibonacciSupplier implements Supplier<Long> {
long a = 0;
long b = 1;
@Override
public Long get() {
long x = a + b;
a = b;
b = x;
return a;
}
}
public class FibonacciStream {
public static void main(String[] args) {
Stream<Long> fibonacci = Stream.generate(new FibonacciSupplier());
fibonacci.limit(10).forEach(System.out::println);
}
}
如果想取得數列的前10項,用limit(10),如果想取得數列的第20~30項,用:
List<Long> list = fibonacci.skip(20).limit(10).collect(Collectors.toList());
最後通過collect()方法把Stream變為List。該List存儲的所有元素就已經是計算出的確定的元素了。
用Stream表示Fibonacci數列,其介面比任何其他介面定義都要來得簡單靈活並且高效。
⑵ Java8 新特性中的Stream,如何按照條件替換原來stream中的數據
1、首先利用foreach()方法對Stream元素進行遍歷,如下圖所示。
⑶ 怎麼用Lambda遍歷List<Map<String,Object>>得到Map<String,String>
public static void main(String[] args) throws Exception {
List<Map<String, Object>> testList = new ArrayList<>();
Map<String, Object> m1 = new HashMap<>();
m1.put("a", "a1");
m1.put("b", "b1");
m1.put("x", "x1");
Map<String, Object> m2 = new HashMap<>();
m2.put("a", "a2");
m2.put("b", "b2");
m2.put("x", "x2");
Map<String, Object> m3 = new HashMap<>();
m3.put("a", "a3");
m3.put("b", "b3");
m3.put("x", "x3");
testList.add(m1);
testList.add(m2);
testList.add(m3);
Map<String, String> m4 = new HashMap<>();
testList.stream().forEach(m -> {
m4.put((String) m.get("a"), (String) m.get("b"));
});
m4.forEach((x, y) -> {
System.out.println(x + y);
});
System.out.println("end");
}
⑷ Java8 新特性 stream().map 能不能跳過元素 ,相當於continue的作用
你好,很高興回答你的問題。
stream()可以調用filter方法,可以用來過濾只保留符合條件的數據,相當於是循環到不符合條件的數據時continue。
如果有幫助到你請點擊採納。
⑸ Java stream中map和forEach有什麼區別
我給你貼段代碼你一看就知道了:
關於stream中map的用法:
Map
data=new
HashMap<>();
data.put(1,
10);
data.put(2,
20);
data.put(3,
30);
List
list
=
data.entrySet().stream().map(Entry::getValue).collect(Collectors.toList());
System.out.println(list);
結果:[10,
20,
30]
這其中map就是把entry的value值映射出來,最後再用Collectors轉成list
關於stream.forEach的用法
map.forEach((k,v)->{
System.out.println(v);
});
純粹就是用流來實現遍歷的語法糖
⑹ java8的stream().mapToInt()什麼意思
Stream(流)是一個來自數據源的元素隊列並支持聚合操作
<strong元素隊列< strong="">元素是特定類型的對象,形成一個隊列。 Java中的Stream並不會存儲元素,而是按需計算。
數據源 流的來源。 可以是集合,數組,I/O channel, 產生器generator 等。
聚合操作 類似SQL語句一樣的操作, 比如filter, map, rece, find, match, sorted等。
可以試試這個輸出什麼:
String[] strarr = {"abc", "defg", "vwxyz"};
int iSum = Arrays.stream(strarr)
.mapToInt(s -> s.length())
.sum();
System.out.println("長度和: "+iSum);
(6)javastream過濾map擴展閱讀:
Java還包括一個類的擴展集合,分別組成各種程序包(Package),用戶可以在自己的程序中使用。例如,Java提供產生圖形用戶介面部件的類(java.awt包),這里awt是抽象窗口工具集(abstract windowing toolkit)的縮寫,處理輸入輸出的類(java.io包)和支持網路功能的類(java.net包)。
⑺ Java8,stream().map().collect(Collectors.toList()).forEach()和stream().map().forEach()有啥區別
最主要的區別的就是stream的方式不一定按照原有List的順序遍歷,而直接用for會按照之前的順序進行遍歷,當然stream會更快一點。看具體使用場景
⑻ java.util.stream map和flatmap的區別
Stream是元素的集合,這點讓Stream看起來用些類似Iterator;
可以支持順序和並行的對原Stream進行匯聚的操作;
大家可以把Stream當成一個高級版本的Iterator。原始版本的Iterator,用戶只能一個一個的遍歷元素並對其執行某些操作;高級版本的Stream,用戶只要給出需要對其包含的元素執行什麼操作,比如「過濾掉長度大於10的字元串」、「獲取每個字元串的首字母」等,具體這些操作如何應用到每個元素上,就給Stream就好了!(這個秘籍,一般人我不告訴他:))大家看完這些可能對Stream還沒有一個直觀的認識,莫急,咱們來段代碼。
//Lists是Guava中的一個工具類
List<Integer> nums = Lists.newArrayList(1,null,3,4,null,6);
nums.stream().filter(num -> num != null).count();
上面這段代碼是獲取一個List中,元素不為null的個數。這段代碼雖然很簡短,但是卻是一個很好的入門級別的例子來體現如何使用Stream,正所謂「麻雀雖小五臟俱全」。我們現在開始深入解刨這個例子,完成以後你可能可以基本掌握Stream的用法!
1.1 剖析Stream通用語法
圖片就是對於Stream例子的一個解析,可以很清楚的看見:原本一條語句被三種顏色的框分割成了三個部分。紅色框中的語句是一個Stream的生命開始的地方,負責創建一個Stream實例;綠色框中的語句是賦予Stream靈魂的地方,把一個Stream轉換成另外一個Stream,紅框的語句生成的是一個包含所有nums變數的Stream,進過綠框的filter方法以後,重新生成了一個過濾掉原nums列表所有null以後的Stream;藍色框中的語句是豐收的地方,把Stream的裡麵包含的內容按照某種演算法來匯聚成一個值,例子中是獲取Stream中包含的元素個數。如果這樣解析以後,還不理解,那就只能動用「核武器」–圖形化,一圖抵千言!
⑼ 怎麼用java8 lamada 提取集合中每個對象的屬性
要提取屬性的話,用Stream中的map,然後使用方法引用,就可以了
例如Student類中有name屬性
List<Student> students = new ArrayList<Student>();
List<String> names = students.stream().map(Student::getName).collect(Collectors.toList());
⑽ java8 中stream filter 如果屬性為空怎麼判斷
在介紹Java 8的流(Stream)時,我們學會了一些集合操作的實用技巧。現在我們要看看怎樣把這些循環轉換為更簡潔,可讀性更高的代碼。 開始編碼! 好吧,講的夠多了,是時候展示一些例子了! 這次我們要以文章為例子。一篇文章擁有一個標題