Java:聚集操作,java聚集操作
你使用集合的目的是什嗎?當然不是為了簡單的儲存然後置之不理,你是為了從集合取資料和操作資料的。
再次考慮前一篇文章提到的背包類,
如果要列印所有背包的重量,
for(Package p : packages) System.out.println(p.getWeight());
遍曆,可以使用"forEach"這一聚集操作,
packages.stream() .forEach(e -> System.out.println(p.getWeigh());
看不懂文法不要緊。我們再來個稍微複雜一點的,
我們只列印“重量大於20的背包重量”,
packages.stream() .filter(e -> e.getWeight() > 20) .forEach(e - > System.out.println(e.getWeight());
分析其結構,
packages是個集合,stream()方法是擷取其“流”,能產生流的不只是集合,數組,I/O通道都可以。下面就是管道操作(和MongoDB或是Linux下的管道類似)了。即有0個或若干個中間操作,如這裡的filter,來產生新的流,然後有一個終結操作,它可以有返回值(不再是一個流),也可以沒有返回值。
其中,filter的函數原型是:
Stream<T> filter<Predicate<? super T> p)
接受一個謂詞參數(條件)。
查看java.util.strem下面的API,其操作時很多的,部分如下,
具體用法不一一介紹。
我們再看一個需求,求“重量大於20的背包的平均重量”。
double average = packages .stream() .filter(e -> e.getWeight() > 20) .mapToInt(e -> e.getWeigh()) .average() .getAsDouble();
除了filter表示過濾,還有maptoInt,返回一個IntStream。
函數原型是,
IntStream maptoInt(toIntFunction<? super T> mapper)
其參數是一個返回Int的lambda運算式。
average()是IntStream的方法,很明顯,是取平均值的,返回一個OptionalDouble,你可以回想OptionalDouble是什嗎?怎麼不直接返回Double!!OptionalDouble是java8新加的,類似的API很多,它的特點是該對象可能包含也可能不包含一個值。作用在於:傳統方法返回一個為Null的值,繼續操作會報NullException,如果OptionalXX沒有值,是可以繼續操作的(當然沒有值getAsDouble會報NoSuchElement異常。
另外,average這個終結操作也是reduction 操作。
在JDK裡面,像average,sum,min等都是通過組合流的內容返回一個值,這些操作稱為reduction操作。當然,有點reduction操作返回一個集合而不是一個值。值得一提的是,JDK還提供了兩個一般化的操作:reduce和collect。
假設我們需要對背包容量求和,
Integer total = packages .stream() .mapToInt(e -> e,getWeight()) .sum();
如果要用reduce對它改造,
Integer total = packages .stream() .mapToInt(e -> e,getWeight()) .reduce(0,(a,b) -> a + b);
如果使用函數引用,
Integer total = packages .stream() .mapToInt(e -> e,getWeight()) .reduce(0,Integer::sum);
查看reduce的函數原型:
T reduce(T indentidy,BinaryOperator<T> accumulator)
這可能比較費解,
API是這樣介紹的,using the provided identity value and an associative accumulation function。
先看是associative,“結合性”,就是說要滿足,
a op b op c = a op (b op c)
像加法,最小值,最大值,字元拼接都有這個性質。
API 還說,reduce函數等價於,
T result = identity; for (T element : this stream) result = accumulator.apply(result, element) return result;
那identy是什麼呢?對於操作的集合的所有t,應該有
accumulator.apply(identity, t) = t
是的,它就是離散數學裡面提到的1元。對加法而言,1元就是0。
reduce操作總會返回新的值。然而,累積函數在每次處理流中的一個元素時也返回一個新的值。假設你要把流“reduce”成一個集合,你每添加一個元素處理就會產生一個新的結合,這顯然是個效能上的缺憾,是很低效的。這時,你可以考慮更新已有的集合。這就是collect方法做的事情。
下一篇再介紹collect的使用細節。
java,位操作?
減一啊~
反向操作嘛~
參考我以前回答過的問題
參考資料:z.baidu.com/question/75765111.html
JAVA 文本操作
說的不是很詳細哎……這個規則意思其實是:漢字算一個,非漢字算0.5個吧;按照每行最多19個的要求,其實18.5個也是有可能要換行的(18個漢字加一個標點加一個漢字就超過了,所以18.5個就要換行),按照這樣的理解,代碼如下:
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class t1 {
public static void main(String args[]) throws IOException{
String path1 = "F:\\test1.txt";
String path2 = "F:\\test2.txt";
Pattern p1 = Pattern.compile("[\u4e00-\u9fa5]");
Reader r1 =new InputStreamReader(new FileInputStream(path1));
BufferedWriter bw = new BufferedWriter(new FileWriter(path2));
int c=0;
float count=0;
StringBuffer bfStr = new StringBuffer();
while((c=r1.read())!=-1){
String str = (char)c+"";
Matcher m = p1.matcher(str);
if(m.matches()){
count++;
}else{
count += 0.5;
}
if((char)c=='\r'){
bw.write(bfStr.toString());
bw.newLine();
bfStr = new StringBuffer();
count = 0;
}else{
if(count>19){
bw.write(bfStr.toString());
bw.newLine();
bfStr = new StringBuffer();
bfStr.append(str);
count=0;
}else{
bfStr.append(str);
}
}
}
if(bfStr.toString()!=""){
bw.write(bfStr.toString());
}
bw.close();
}
}
補充一句:原來文本的換行格式給你保留了,一般這個不會讓你改的吧,你也沒說清楚。。。...餘下全文>>