Strem流计算
以声明的方式处理集合
Java 8 API添加了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。
Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。
Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。
这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。
元素流在管道中经过中间操作(intermediate operation)的处理,最后由最终操作(terminal operation)得到前面处理的结果。
+--------------------+ +------+ +------+ +---+ +-------+ | stream of elements +-----> |filter+-> |sorted+-> |map+-> |collect| +--------------------+ +------+ +------+ +---+ +-------+
以上的流程转换为 Java 代码为:
List<Integer> transactionsIds = widgets.stream() .filter(b -> b.getColor() == RED) .sorted((x,y) -> x.getWeight() - y.getWeight()) .mapToInt(Widget::getWeight) .sum();
什么是 Stream?
Stream(流)是一个来自数据源的元素队列并支持聚合操作
- 元素是特定类型的对象,形成一个队列。 Java中的Stream并不会存储元素,而是按需计算。
- 数据源 流的来源。 可以是集合,数组,I/O channel, 产生器generator 等。
- 聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等。
和以前的Collection操作不同, Stream操作还有两个基础的特征:
- Pipelining: 中间操作都会返回流对象本身。 这样多个操作可以串联成一个管道, 如同流式风格(fluent style)。 这样做可以对操作进行优化, 比如延迟执行(laziness)和短路( short-circuiting)。
- 内部迭代: 以前对集合遍历都是通过Iterator或者For-Each的方式, 显式的在集合外部进行迭代, 这叫做外部迭代。 Stream提供了内部迭代的方式, 通过访问者模式(Visitor)实现。
生成流
在 Java 8 中, 集合接口有两个方法来生成流:
- stream() − 为集合创建串行流。
- parallelStream() − 为集合创建并行流。
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
forEach
Stream 提供了新的方法 'forEach' 来迭代流中的每个数据。以下代码片段使用 forEach 输出了10个随机数:
Random random = new Random(); random.ints().limit(10).forEach(System.out::println);
filter
filter 方法用于通过设置的条件过滤出元素。以下代码片段使用 filter 方法过滤出空字符串:
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); // 获取空字符串的数量 long count = strings.stream().filter(string -> string.isEmpty()).count();
limit skip去除
limit 方法用于获取指定数量的流。 以下代码片段使用 limit 方法打印出 10 条数据:
Random random = new Random(); random.ints().limit(10).forEach(System.out::println);
sorted
sorted 方法用于对流进行排序。以下代码片段使用 sorted 方法对输出的 10 个随机数进行排序:
Random random = new Random(); random.ints().limit(10).sorted().forEach(System.out::println);
并行(parallel)程序
parallelStream 是流并行处理程序的代替方法。以下实例我们使用 parallelStream 来输出空字符串的数量:
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); // 获取空字符串的数量 long count = strings.parallelStream().filter(string -> string.isEmpty()).count();
我们可以很容易的在顺序运行和并行直接切换。
flatMap
使用这个方法的效果,就是可以将每个生成的流合并为一个流,也就是扁平化,在说明一下,flatMap方法让你把一个流中的每一个值都换成另一个流,然后把所有的流链接起来。
Arrays.stream(words) .map(word -> word.split("")) .flatMap(Arrays::stream) .distinct() .collect(Collectors.toList());
Collectors
Collectors 类实现了很多归约操作,例如将流转换成集合和聚合元素。Collectors 可用于返回列表或字符串:
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList()); System.out.println("筛选列表: " + filtered); String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", ")); System.out.println("合并字符串: " + mergedString);
统计
另外,一些产生统计结果的收集器也非常有用。它们主要用于int、double、long等基本类型上,它们可以用来产生类似如下的统计结果。
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics(); System.out.println("列表中最大的数 : " + stats.getMax()); System.out.println("列表中最小的数 : " + stats.getMin()); System.out.println("所有数之和 : " + stats.getSum()); System.out.println("平均数 : " + stats.getAverage());
分组
groupingBy 方法,简单理解来说,就是分组,返回的是一个Map。在它之前的分组是这样的:
appleByColorMap = appleAllList.stream().collect(groupingBy(Apple::getColor));
在这里,你给groupingBy传递了一个方法,它是获取苹果的颜色的,这个叫分类函数。按照函数的结果来进行分组,函数的结果也就作为了key值。当然了,有时候业务需求上的分组并不向这样简单,这个时候我们也可以自定义分组函数:
list.stream().collect(groupingBy(apple -> { if (apple.getWeight() > 300) { return "Heavy"; } else if (apple.getWeight() < 200) { return "little"; } else { return "normal"; }
求和操作
Long allWeight = appleAllList.stream().collect(summingLong(Apple::getWeight)); //平均数 Double collectAvg = appleAllList.stream().collect(averagingLong(Apple::getWeight)); 在数据统计中,最大值,最小值,求和,平均值可能你都想得到,这样一次次的获取可能不太方便,想着一次操作就可以,你可以使用summarizingInt工厂方法返回的收集器。例如,通过一次summarizing操作你可以就得到以上的结果 LongSummaryStatistics summaryStatistics = appleAllList.stream().collect(summarizingLong(Apple::getWeight));
连接字符串
String nameStr = appleAllList.stream().map(Apple::getName).collect(joining()); //还有一个重载的版本 String nameStr = appleAllList.stream().map(Apple::getName).collect(joining(",")); 以上的收集器都是可以用reducing工厂方法定义的归约过程的特殊情况而已 appleAllList.stream().map(Apple::getWeight).reduce((i, j) -> i + j); appleAllList.stream().collect(reducing(0,(a1, a2) -> a1.getWeight() > a2.getWeight() ? a1 : a2)); reduce操作需要3个参数:起始值;转换的函数;一个BinaryOperator,将两个元素合成一个同类型的值。
reversed反序排列
集合元素指定排序(按age升序排序),并取反序。
private static void reverseTest() { List<User> users = getUsers(); users = users.stream() .sorted(Comparator.comparingInt(User::getAge).reversed()) .collect(Collectors.toList()); log.info("指定排序,并取反序:{}", users); }
findFirst获取第一个元素
取集合中第一个元素。
private static void findFirstTest() { List<User> users = getUsers(); User firstUser = users.stream() .findFirst() .orElse(null); log.info("集合中第一个元素为:{}", firstUser); }
findAny获取集合中任意一个元素
取集合中任意一个元素。
private static void findAnyTest() { List<User> users = getUsers(); User anyUser = users.stream() .findAny() .orElse(null); log.info("集合中任意一个元素为:{}", anyUser); }
min最小值
取集合中年龄最小的元素.。
private static void minTest() { List<User> users = getUsers(); User anyUser = users.stream() //.min((u1, u2) -> u1.getAge() - u2.getAge()) .min(Comparator.comparingInt(User::getAge)) .orElse(null); log.info("集合中年龄最小的元素为:{}", anyUser); }
max最大值
取集合中年龄最大的元素。
private static void maxTest() { List<User> users = getUsers(); User anyUser = users.stream() //.max((u1, u2) -> u1.getAge() - u2.getAge()) .max(Comparator.comparingInt(User::getAge)) .orElse(null); log.info("集合中年龄最大的元素为:{}", anyUser); }
anyMatch任意元素匹配
集合中任意一个元素满足条件,返回true;反之,返回false
private static void anyMatchTest() { List<User> users = getUsers(); boolean matchFlag = users.stream() .anyMatch(user -> Objects.equals(user.getName(), "李四")); log.info("集合中是否存在名为'李四'的元素:{}", matchFlag); }
allMatch所有元素匹配
集合中所有元素满足条件,返回true;反之,返回false。
private static void allMatchTest() { List<User> users = getUsers(); boolean matchFlag = users.stream() .allMatch(user -> user.getAge() > 20); log.info("集合中所有元素的年龄是否都大于20岁:{}", matchFlag); }
noneMatch所有元素不匹配
集合中所有元素都不满足条件,返回true;反之,返回false。
private static void noneMatchTest() { List<User> users = getUsers(); boolean matchFlag = users.stream() .noneMatch(user -> user.getAge() <= 20); log.info("集合中是否所有元素的年龄都不小于等于20岁:{}", matchFlag); }
map集合值映射
集合值映射。
private static void mapTest() { List<User> users = getUsers(); List<String> names = users.stream() // .map(user -> user.getName()) .map(User::getName) .collect(Collectors.toList()); log.info("集合中所有对象的名称集合为:{}", names); }
flatMap集合值扁平映射
集合值扁平映射。
private static void flatMapTest() { List<User> users = getUsers(); List<String> allHobbies = users.stream() .flatMap(user -> user.getHobbies().stream()) .collect(Collectors.toList()); log.info("集合中所有用户的所有兴趣爱好列表:{}", allHobbies); }
map+reduce聚合求值
聚合求值。
private static void mapReduceTest() { List<User> users = getUsers(); int ageSum = users.stream() // .map(user -> user.getAge()) .map(User::getAge) .reduce(0, (age1, age2) -> age1 + age2); log.info("集合中所有用户年龄总和:{}", ageSum); }
parallel并行流
并行流处理。
private static void parallelStreamTest() { List<User> users = getUsers(); //下面两种方式等效 users.stream() .parallel() .forEach(user -> { //业务处理 log.info(".stream.parallel并行遍历当前元素为:{}", user); }); users.parallelStream() .parallel() .forEach(user -> { //业务处理 log.info(".parallelStream并行遍历当前元素为:{}", user); }); }
distinct去重
去重(name相同认为是同一用户)。需要重写User.java类的equals()和hashCode()方法。
private static void distinctTest() { //users集合里面有两个name为“李四”的用户 List<User> users = getUsers(); users = users.stream() .distinct() .collect(Collectors.toList()); log.info("去重(name相同认为是同一用户):{}", users); }
String str3 = Arrays.stream(arr).boxed().map(Object :: toString).reduce("", String::concat); // 方法引用Object::toString
int[] originalArray = {1, 2, 3, 4, 5}; int[] first2Elements = Arrays.copyOfRange(originalArray,0,2);//切割字符串 int[] last3Elements = Arrays.copyOfRange(originalArray,2,5);
int[] originalArray = {1, 2, 3, 4, 5}; int[] newArray = Arrays.copyOf(originalArray, 10);//copy成为一个新的字符串(10)
int[] values = Arrays.stream(characters).mapToInt(Integer::valueOf).toArray();
System.arraycopy
* @param src the source array. * @param srcPos starting position in the source array. * @param dest the destination array. * @param destPos starting position in the destination data. * @param length the number of array elements to be copied. Person[] srcPersons=srcList.toArray(new Person[0]); Person[] destPersons=new Person[srcPersons.length]; System.arraycopy(srcPersons, 0, destPersons, 0, srcPersons.length);
求和
final List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); int sum = numbers.stream().mapToInt(Integer::valueOf).sum();
集合转string数组
Collection<String> arrayCollection = new LinkedList<>(); arrayCollection.add("Amy"); arrayCollection.add("Bob"); arrayCollection.add("Carl"); String[] array = arrayCollection.toArray(new String[arrayCollection.size()]);
string去大小写重
Set<String> strings =new TreeSet<>(Comparator.comparing(String::toLowerCase)); Collectors.collectingAndThen( Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Person::getName))), ArrayList::new)); Set<String> strings =new TreeSet<>(Comparator.comparing(String::toLowerCase)); strings.addAll(collection); return new ArrayList<>(strings);
逆序
//字符串逆序 String[] originalArray = {"A", "quick", "brown", "fox"}; String[] reversed =IntStream.range(0,originalArray.length).mapToObj(i -> originalArray[originalArray.length - i - 1]).toArray(size -> new String[size]); "fox", "brown", "quick", "A"} //自然降序 list.stream().sorted(Comparator.reverseOrder()); nums = Arrays.stream(nums).boxed().sorted((a, b) -> b - a).mapToInt(p -> p).toArray(); //升序 list.stream().sorted().reversed());//int可以直接用 list.stream().sorted(Comparator.comparing(Student::getAge).reversed())
统计字符串个数
``//方式2 使用流 ``//这个在测试特殊字符,比如\ \n时,他的顺序会不对,这个是Map造成的 ``//解决办法使用TreeMap ``public static void letterCount2(String s) { ``s``=s.replaceAll(" +", ""); ``TreeMap<String, Long> result = Arrays.stream(s.split("")) ``.sorted() // .collect(Collectors.groupingBy(Function.identity(),Collectors.counting())); ``.collect(Collectors.groupingBy(Function.identity(),TreeMap::new,Collectors.counting())); ``System.out.println(result); //取出非字符串的 text=text.toLowerCase().replaceAll("[^a-z]",""); //变成char流然后变成map的Obj最会装箱 Character[] chars =text.chars().mapToObj(c -> (char)c).toArray(Character[]::new); Map<Character, Long> histogram= Arrays.stream(chars).sorted() .collect(Collectors.groupingBy(Function.identity(),HashMap::new,Collectors.counting()));
转为Character[]
方式一:推荐,无需import
1 String str = "testString"; 2 Character[] charObjectArray = str.chars().mapToObj(c -> (char)c).toArray(Character[]::new);
java中获取字符的unicode值(适用于所有字符)
String y = new String(Character.toChars(0x2B85B)); // code point转字符串 System.out.println(y.codePointAt(0)); // 字符串转 code point
String y1 = new StringBuilder().appendCodePoint(0x2B85B).toString(); // StringBuilder 也支持 code point System.out.println(y1);
String x = "\uD86E\uDC5B"; System.out.println(x);
/** * char 不同的赋值类型 */ //char c = '\u0061'; //char c = 0x61; //char c = 97; char c = 'a'; System.out.println(c);
###
Java Parallel Stream如何生成HashMap?
- 回答 (2)
- 关注 (0)
- 查看 (2082)
有以下测试,测试从0到最大的整数,如果它被验证,构造对(vals [i],i)。最后,我想生成一个HashMap,它使用vals [i]作为键,值是整数列表。代码看起来像,
IntStream.range(0, max) .parallel() .filter(i-> sometest(i)) .mapToObj(i -> new Pair<>(vals[i],i)) .collect(groupingBy(Pair::getFirst, mapping(Pair::getSecond, toList())));
Cmder优化传统win命令行界面
Cmder是一个软件包,它是在Windows上缺少出色的控制台模拟器的情况下,出于纯粹的沮丧而创建的。它基于出色的软件,并采用了Monokai配色方案和自定义提示布局,从一开始就看起来很性感。
Tab manipulation
- Ctrl + `: 从任务栏全局召唤
Win + Alt + p
:首选项(或右键单击标题栏)
Ctrl + t
:“新标签”对话框(也许您想以管理员身份打开cmd?)
Ctrl + w
:关闭标签
Shift + Alt + number
1.
CMD2.
电源外壳
:快速新标签:
Alt + Enter
: 全屏
Shell
Ctrl + Alt + u
: Traverse up in directory structure (lovely feature!)
End, Home, Ctrl
: Traverse text as usual on Windows
Ctrl + r
: History search
Shift + mouse
: Select and copy text from buffer
Right click / Ctrl + Shift + v
: Paste text
js
Running Unit Test
$ npm test
如果要运行与某些模式匹配的测试,可以运行: $ npm test -- <pattern> 列如: $ npm test -- receptionist
Linting Your Code
您可以使用以下命令检查代码是否违反了编码标准:
$ npm run lint
SonarQube Analysis Your Code
$ npm run sonarqube
ps: Windows user use the following command
$ ./sonar-scan.sh
切换淘宝镜像
npm config set registry http://registry.npm.taobao.org 如果node-sass安装不成功换成下面的镜像 npm config set registry http://npm.taobao.org
切换默认镜像
npm config set registry https://registry.npmjs.org
数组操作
shift()删除第一个 pop()删除最后一个 unshift()添加在头部
冻结对象不能进行添加
javaScript提供了
Object.freeze
防止数据突变的功能。let obj = { name:"FreeCodeCamp", review:"Awesome" }; Object.freeze(obj); obj.review = "bad"; obj.newProp = "Test"; console.log(obj);
在
obj.review
和obj.newProp
分配将导致错误,并在控制台显示的值{ name: "FreeCodeCamp", review: "Awesome" }
。函数值
const greeting = (name = "Anonymous") => "Hello " + name; console.log(greeting("John")); console.log(greeting());
控制台将显示字符串
Hello John
和Hello Anonymous
。将Rest参数与Function参数一起使用
reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
reduce() 可以作为一个高阶函数,用于函数的 compose。
注意: reduce() 对于空数组是不会执行回调函数的。
array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
参数
描述
function(total,currentValue, index,arr)
必需。用于执行每个数组元素的函数。 函数参数:参数描述total必需。初始值, 或者计算结束后的返回值。currentValue必需。当前元素currentIndex可选。当前元素的索引arr可选。当前元素所属的数组对象。
initialValue
可选。传递给函数的初始值
array.filter(function(currentValue,index,arr), thisValue)
参数
描述
function(currentValue, index,arr)
必须。函数,数组中的每个元素都会执行这个函数 函数参数: 参数描述currentValue必须。当前元素的值index可选。当前元素的索引值arr可选。当前元素属于的数组对象
thisValue
可选。对象作为该执行回调时使用,传递给函数,用作 "this" 的值。 如果省略了 thisValue ,"this" 的值为 "undefined"
使用Spread运算符就地评估数组
下面的ES5代码
apply()
用于计算数组中的最大值:var arr = [6, 89, 3, 45]; var maximus = Math.max.apply(null, arr);
maximus
的值为89
。优化👇
const maximus = Math.max(...arr);
maximus
的值为89
。Array.from(arr);拷贝数组
Array.prototype.slice()
*slice()**
方法返回一个新的副本对象,该对象是一个由begin
和end
决定的原先的浅拷贝(包括begin
,不包括end
)。原始序列不会被改变。
const animals = ['ant', 'bison', 'camel', 'duck', 'elephant'];
console.log(animals.slice(2));
// expected output: Array ["camel", "duck", "elephant"]
class
class SpaceShuttle { constructor(targetPlanet) { this.targetPlanet = targetPlanet; } } const zeus = new SpaceShuttle('Jupiter');
import * as myMathModule from "./math_functions.js";
test
JavaScript有多种使用正则表达式的方法。一种测试正则表达式的
.test()
方法是使用该方法。该.test()
方法采用正则表达式,将其应用到字符串(放在括号内),然后返回,true
或者false
如果您的模式找到了什么,则返回。map
const users = [ { name: 'John', age: 34 }, { name: 'Amy', age: 20 }, { name: 'camperCat', age: 10 } ]; const names = users.map(user => user.name); 处理多行 ratings= watchList.map(watch=>({title:watch.Title,rating:watch.imdbRating}))