Stream初步认识(一)测试

简介


Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对 集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。 使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数 据库查询。也可以使用 Stream API 来并行执行操作。简而言之, Stream API 提供了一种高效且易于使用的处理数据的方式。

流(Stream)到底是什么?

**是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。 ,“集合讲的是数据,流讲的是计算! ” **

注:

java.util.Stream表示了某一种元素的序列,在这些元素上可以进行各种操作。Stream操作可以是中间操作,也可以是完结操作。完结操作会返回一个某种类型的值,而中间操作会返回流对象本身并且你可以通过多次调用同一个流操作方法来将操作结果串起来(就像StringBuffer的append方法一样————译者注)。Stream是在一个源的基础上创建出来的,例如java.util.Collection中的list或者set(map不能作为Stream的源)。Stream操作往往可以通过顺序或者并行两种方式来执行。

注意:

  1. Stream关注的是对数据的运算,与CPU打交道集合关注的是数据的存储,与内存打交道
  2. ①Stream 自已不会储存元素。

    ②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream

    ③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行(类似于懒加载)

Stream操作

stream操作步骤


  1. 创建Stream:一个数据源(如:集合,数组,Map不可以作为数据源)获取一个流
  2. 中间操作:一个中间操作链,对数据源的数据进行操作处理(过滤、映射...)
  3. 终止操作(终端操作):一个终止操作,执行中间操作链,并产生结果(一旦执行终止操作,就执行中间操作链,并产生结果。之后的,不会再被使用)

操作流程如下图:

Stream实例化的方式


  • 通过集合
  • 通过数组
  • 通过Stream的of()
  • 通过无限流

    下面我们一一通过代码示例进行详细解析:

公共代码(测试使用)

公共集合
    List<Person> javaProgrammers = new ArrayList<Person>() {
{
add(new Person("Elsdon", "Jaycob", "Java programmer", "male", 2000, 18));
add(new Person("Tamsen", "Brittany", "Java programmer", "female", 2371, 55));
add(new Person("Floyd", "Donny", "Java programmer", "male", 3322, 25));
add(new Person("Sindy", "Jonie", "Java programmer", "female", 35020, 15));
add(new Person("Vere", "Hervey", "Java programmer", "male", 2272, 25));
add(new Person("Maude", "Jaimie", "Java programmer", "female", 2057, 87));
add(new Person("Shawn", "Randall", "Java programmer", "male", 3120, 99));
add(new Person("Jayden", "Corrina", "Java programmer", "female", 345, 25));
add(new Person("Palmer", "Dene", "Java programmer", "male", 3375, 14));
add(new Person("Addison", "Pam", "Java programmer", "female", 3426, 20));
add(new Person("Addison", "Pam", "Java programmer", "female", 3422, 20));
add(new Person("Addison", "Pam", "Java programmer", "female", 3429, 20));
// add(new Person("Addison", "Pam", "Java programmer", null, 3422, 20));
}
};
公共实体类
package com.zy.stream.model;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor; @Data
@Builder(toBuilder = true)
@AllArgsConstructor
@NoArgsConstructor
public class Person { private String firstName, lastName, job, gender;
private int salary,age; }

通过集合创建Stream流

        //1.1   通过集合创建Stream流------> default Stream<E> stream:返回一个顺序流
Stream<Person> stream=javaProgrammers.stream(); //1.2 通过集合创建Stream流------> default Stream<E> parallelStream:返回一个并行流
Stream<Person> parallelStream = javaProgrammers.parallelStream();

我们通过集合javaProgrammers创建了Stream流,那么为什么会返回一个流呢?

我们看Collection集合类的源码:

	//1.1	当集合集合调用stream()时,return一个Stream<E>
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
//1.2 同理
default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}

通过数组创建Stream流

        //2.1   通过数组创建Stream流-------> 调用Arrays类的static <T> Stream<T>  Stream<T[] array> :返回一个流
Person[] arrPerson = new Person[]{javaProgrammers.get(0),javaProgrammers.get(1)};
Stream<Person> streamObj = Arrays.stream(arrPerson);

通过静态类Arrays调用Stream中的静态Stream方法,即可返回一个流。

静态Stream方法源码:

//入参Array数组,返参 <T> Stream<T>流
public static <T> Stream<T> stream(T[] array) {
return stream(array, 0, array.length);
}
public static <T> Stream<T> stream(T[] array, int startInclusive, int endExclusive) {
return StreamSupport.stream(spliterator(array, startInclusive, endExclusive), false);
}

通过Stream的of方法创建流

      //3.1   通过of创建Stream
Stream<Integer> streamOf = Stream.of(1, 2, 3, 4, 5, 6); Stream<Person> streamOfs = Stream.of(javaProgrammers.get(0),javaProgrammers.get(1));

of方法源码:

    @SafeVarargs
@SuppressWarnings("varargs") // Creating a stream from an array is safe
public static<T> Stream<T> of(T... values) {
//通过of源码我们可以看到,其实of方法任然是使用的是数组的创建的方式,只是外部有包了一层
return Arrays.stream(values);
}

通过无线流的创建Stream流

        //4.1   通过无限流的方式创建Stream流
/*4.1.1 迭代--->*public static<T> Stream<T> iterate(final T seed,final UnaruOperator<T> f)
* 遍历前10个偶数
* 无限流,无限反复操作使用,所有一般都会配合limit使用
*/
Stream.iterate(0,t->t+2).limit(10).forEach(System.out::println); //seed是起始数值,limit代表循环前10次 //4.1.2 生成----》public static<T> Stream<T> generate(Supplier<T> s)
Stream.generate(Math::random).limit(10).forEach(System.out::println);

小结

(1)Java8 中的 Collection 接口被扩展,提供了 两个获取流的方法:

default Stream stream() : 返回一个顺序流

default Stream parallelStream() : 返回一个并行流

(2)Java8 中的 Arrays 的静态方法 stream() 可 以获取数组流:

static Stream stream(T[] array): 返回一个流

重载形式,能够处理对应基本类型的数组:

public static IntStream stream(int[] array)

public static LongStream stream(long[] array)

public static DoubleStream stream(double[] array)

(3)可以使用静态方法 Stream.of(), 通过显示值 创建一个流。它可以接收任意数量的参数。

public static Stream of(T... values) : 返回一个流

可以使用静态方法 Stream.iterate() 和 Stream.generate(), 创建无限流。

1.** 迭代**

public static Stream iterate(final T seed, final UnaryOperator f)

2.生成

public static Stream generate(Supplier s)

Stream流的中间操作


中间操作有:

  1. 筛选和切片

    filter(Predicate p)–接受Lambda,从流中排除某些元素

    limit(n)–截断流,使其元素不超过给定数量

    skip(n)–跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与limit(n)互补

    distinct–筛选,通过流所生成的元素的 hashCode() 和 equals() 去除重复元素
  2. 映射

    map(Function f)–接受一个函数作为参数,将元素转换成其他形式或提取信息,该函数会被应用到每个元素上,并将其映射成一个新的元素。

    flatMap(Function f)–接受一个函数作为参数,将流中的每个值都转换成另一个流,然后把所有流连成一个流
  3. ** 排序**

    sorted()–自然排序,产生一个新流,其中按自然顺序排序

    sorted(Comparator com)–定制排序,产生一个新流,其中按比较器顺序排序

下面我们通过代码实现来分析这些方法:

筛选和切片


filter()方法


Filter接受一个predicate接口类型(断言型函数式接口)的变量,并将所有流对象中的元素进行过滤。该操作是一个中间操作,因此它允许我们在返回结果的基础上再进行其他的流操作(比如:forEach)。ForEach接受一个function接口类型的变量,用来执行对每一个元素的操作。ForEach是一个中止操作。它不返回流,所以我们不能再调用其他的流操作。

   @Test
public void testFilter() {
//1.1 `filter`(Predicate p)–接受Lambda,从流中排除某些元素
//1.1.1 原生方式 所有的中间操作不会做任何的处理
Stream<Person> stream = javaProgrammers.stream()
.filter((e) -> {
System.out.println("测试中间操作");
return e.getAge() < 20;
});
stream.forEach(System.out::println);//只有当做终止操作时,所有的中间操作会一次性的全部执行,称为“惰性求值” //1.1.2 使用lambdas表达式优化
javaProgrammers.stream().filter(e->{
System.out.println("测试中间操作");
return e.getAge() <20;
}).forEach(System.out::println);
}

Limit(N)和Skip(N)方法


    @Test
public void testLimitAndSkip() {
// 1.2 `limit(n)`–截断流,使其元素不超过给定数量 类似于mysql中的limit,但这里只有最大值
//1.3 `skip(n)`–跳过元素,返回一个扔掉了前n个元素的流。若流中元素不足n个,则返回一个空流。与limit(n)互补 //通过无限流创建一个无限流,如果不使用Limit方法进行限制阶段,无限流将会形成一个类似于死循环的操作
//当使用skip()将会跳过前5个数据从第6个参数返回
Stream.iterate(0,t->t+1).limit(10).skip(5).forEach(System.out::println); //seed是起始数值,limit代表循环前10次
}

distinct()方法*


distinct()返回由该流的不同元素组成的流。distinct()是Stream接口的方法。distinct()使用hashCode()和equals()方法来获取不同的元素。我们的类必须实现hashCode()和equals()。如果distinct()正在处理有序流,那么对于重复元素,将保留以遭遇顺序首先出现的元素,并且以这种方式选择不同元素是稳定的。在无序流的情况下,不同元素的选择不一定是稳定的,是可以改变的。distinct()执行有状态的中间操作。在有序流的并行流的情况下,保持distinct()的稳定性是需要很高的代价的,因为它需要大量的缓冲开销。如果我们不需要保持遭遇顺序的一致性,那么我们应该可以使用通过BaseStream.unordered()方法实现的无序流。

distinct对集合中的对象进行去重
        //1.4   `distinct`–筛选,通过流所生成的元素的 hashCode() 和 equals() 去除重复元素

        //1.4.1  distinct取出集合中对象信息完全重复的对象
javaProgrammers.stream().distinct().forEach(System.out::println);

打印结果(对集合后三条重复的数据进行了去重操作):

Person(firstName=Elsdon, lastName=Jaycob, job=Java programmer, gender=male, salary=2000, age=18)
Person(firstName=Tamsen, lastName=Brittany, job=Java programmer, gender=female, salary=2371, age=55)
Person(firstName=Floyd, lastName=Donny, job=Java programmer, gender=male, salary=3322, age=25)
Person(firstName=Sindy, lastName=Jonie, job=Java programmer, gender=female, salary=3502, age=15)
Person(firstName=Vere, lastName=Hervey, job=Java programmer, gender=male, salary=2272, age=25)
Person(firstName=Maude, lastName=Jaimie, job=Java programmer, gender=female, salary=2057, age=87)
Person(firstName=Shawn, lastName=Randall, job=Java programmer, gender=male, salary=3120, age=99)
Person(firstName=Jayden, lastName=Corrina, job=Java programmer, gender=female, salary=345, age=25)
Person(firstName=Palmer, lastName=Dene, job=Java programmer, gender=male, salary=3375, age=14)
Person(firstName=Addison, lastName=Pam, job=Java programmer, gender=female, salary=3422, age=20)
distinct对集合中对象的某一属性进行去重

distinct()不提供按照属性对对象列表进行去重的直接实现。它是基于hashCode()和equals()工作的。如果我们想要按照对象的属性,对对象列表进行去重,我们可以通过其它方法来实现。如下代码段所示:

static <T> Predicate<T> distinctByKey(Function<? super T, ?> keyExtractor) {
Map<Object,Boolean> seen = new ConcurrentHashMap<>();
return t -> seen.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
}

上面的方法可以被Stream接口的 filter()接收为参数,如下所示:

        //1.4.2    distinct对集合中对象的某一属性进行去重

        javaProgrammers.stream().filter(distinctByKey(e->e.getAge())).distinct().forEach(System.out::println);

distinctByKey()方法返回一个使用ConcurrentHashMap 来维护先前所见状态的 Predicate 实例,如下是一个完整的使用对象属性来进行去重的示例。

打印结果(以去除年龄相同的人的信息):

Person(firstName=Elsdon, lastName=Jaycob, job=Java programmer, gender=male, salary=2000, age=18)
Person(firstName=Tamsen, lastName=Brittany, job=Java programmer, gender=female, salary=2371, age=55)
Person(firstName=Floyd, lastName=Donny, job=Java programmer, gender=male, salary=3322, age=25)
Person(firstName=Sindy, lastName=Jonie, job=Java programmer, gender=female, salary=3502, age=15)
Person(firstName=Maude, lastName=Jaimie, job=Java programmer, gender=female, salary=2057, age=87)
Person(firstName=Shawn, lastName=Randall, job=Java programmer, gender=male, salary=3120, age=99)
Person(firstName=Palmer, lastName=Dene, job=Java programmer, gender=male, salary=3375, age=14)
Person(firstName=Addison, lastName=Pam, job=Java programmer, gender=female, salary=3422, age=20)

映射


这个类似于list集合中的add和addAll的区别,add添加一个集合是把集合当成一个元素,addAll添加一个集合是把集合中的每个元素当成一个元素

map(Function f)和flatMap(Function f)方法

map相当于add,flatMap相当于addAll

 @Test
public void testMapAndFlatMap(){
/*2.1 `map(Function f)`–接受一个函数作为参数,将元素转换成其他形式或提取信息,该函数会被应用到每个元素上,并将其映射成一个新的元素。
*
* 这个类似于list集合中的add和addAll的区别,add添加一个集合是把集合当成一个元素,addAll添加一个集合是把集合中的每个元素当成一个元素
* map相当于add,flatMap相当于addAll
*/ //map(Function f)--接受一个函数作为参数,将元素转换成其他形式或提取信息,该函数会被应用到每个元素上,并将其映射成一个新的元素。
List<String> list = Arrays.asList("测试", "bb", "cc", "dd","dsf","dsf");
list.stream().map(s -> s.toUpperCase()).forEach(System.out::println); //练习2.1.1 获取集合中年龄大于20的人
javaProgrammers.stream().map(Person::getAge).filter(e->e>20).forEach(System.out::println); //练习2.1.2 将字符串中的多个字符构成的集合转换为对应的Stream的实例
Stream<Stream<Character>> streamStream = list.stream().map(SteamApiTest::fromStringToStream);//有点麻烦
streamStream.forEach(s->s.forEach(System.out::println)); // 2.2 `flatMap(Function f)`–接受一个函数作为参数,将流中的每个值都转换成另一个流,然后把所有流连成一个流
Stream<Character> characterStream = list.stream().flatMap(SteamApiTest::fromStringToStream);
characterStream.forEach(System.out::println); javaProgrammers.stream().flatMap(e->Stream.of(e).filter(x->x.getAge()>20)).forEach(System.out::println); } //将字符串中的多个字符构成的集合转换为对应的Stream的实例
public static Stream<Character> fromStringToStream(String str){
ArrayList<Character> list = new ArrayList<>(); for (Character c:str.toCharArray()){
list.add(c);
}
return list.stream();
}

排序


自然排序的对象是需要实现Comparable接口的

sorted()方法


    @Test
public void testStore(){
//3.1 sorted()–自然排序,产生一个新流,其中按自然顺序排序 sorted()参数可选,有两个重载一个有参Comparator,一个无参 List<Integer> list = Arrays.asList(12, 43, 65, 3, 4, 0,01, -98);
list.stream().sorted().forEach(System.out::println); //3.1.1 抛异常,原因:Person没有实现Comparable接口
//javaProgrammers.stream().sorted().forEach(System.out::println); //3.2 sorted(Comparator com)–定制排序,产生一个新流,其中按比较器顺序排序,根据条件排序
//多集合中对象根据年龄进行排序
javaProgrammers.stream().sorted((e1,e2)->Integer.compare(e1.getAge(),e2.getAge())).forEach(System.out::println); }

Stream的终止操作(常用方法)


终止操作有:

  1. 匹配与查找

    allMatch(Predicate p):检查是否匹配所有元素

    anyMatch(Predicate p):检查是否至少匹配一个元素

    noneMatch(Predicate p):检查是否没有匹配的元素

    findFirst():返回第一个元素

    findAny():返回当前流中的任意元素

    count():返回流中元素的总数

    max(Comparator c):返回流中最大值

    min(Comparator c):返回流中最小值

    forEach(Consumer c):内部迭代
  2. 规约

    reduce(T identity,BinaryOperator accumulator):可以将流中元素反复结合起来,得到一个值。返回T

    reduce(BinaryOperator accumulator):可以将流中元素反复结合起来,得到一个值。返回Optional
  3. 收集

    collect(Collector c):将流转换成其他形式。接受一个Collector接口的实现,用于给Stream中元素做汇总的方法

匹配与查找


方法都比较简单易于理解。

    @Test
public void testMatchAndFind() {
/**
* 1. 匹配与查找
* allMatch(Predicate p):检查是否匹配所有元素
* anyMatch(Predicate p):检查是否至少匹配一个元素
* noneMatch(Predicate p):检查是否没有匹配的元素
* findFirst():返回第一个元素
* findAny():返回当前流中的任意元素
* count():返回流中元素的总数
* max(Comparator c):返回流中最大值
* min(Comparator c):返回流中最小值
* forEach(Consumer c):内部迭代
**/ //1.1 allMatch()相当于制定一个规则,将集合中的对象一一与规则进行对象,判断是否所有的集合对象都符合该规则, true/false
boolean allMatch = javaProgrammers.stream().allMatch(e -> e.getAge()>18);
System.out.println("测试Stream流的终止操作----allMatch()--->"+allMatch); //1.2 anyMatch(Predicate p):检查是否至少匹配一个元素 类似于多选一即可
boolean anyMatch = javaProgrammers.stream().anyMatch(e -> e.getSalary()>1000);
System.out.println("检查是否至少匹配一个元素----anyMatch()--->"+anyMatch); //1.3 noneMatch(Predicate p):检查是否没有匹配的元素 没有返回true,反之false
boolean noneMatch = javaProgrammers.stream().noneMatch(e -> e.getSalary() > 10000);
System.out.println("检查是否没有匹配的元素----noneMatch()--->"+noneMatch); //1.4 findFirst():返回第一个元素
Person person = javaProgrammers.stream().findFirst().get();
System.out.println("返回第一个元素----findFirst()--->"+person.toString()); for (int i = 0; i <1000 ; i++) {
//1.5 findAny():返回当前流中的任意元素
Optional<Person> AnyPerson = javaProgrammers.stream().findAny();
//System.out.println("返回当前流中的任意元素----findAny()--->"+AnyPerson.toString()+"--------->"+i);
} //1.6 count():返回流中元素的总数
long count = javaProgrammers.stream().count();
System.out.println("返回流中元素的总数----count()--->"+count); //1.7 max(Comparator c):返回流中最大值 Optional<T> max(Comparator<? super T> comparator);
Person maxPersonSalary = javaProgrammers.stream().max(Comparator.comparing(Person::getSalary)).get();
System.out.println("返回流中最大值----max()--->"+maxPersonSalary); //1.8 min(Comparator c):返回流中最小值
Person minPersonSalary = javaProgrammers.stream().min(Comparator.comparing(Person::getSalary)).get();
System.out.println("返回流中最小值----max()--->"+minPersonSalary); }

打印结果:

测试Stream流的终止操作----allMatch()--->false
检查是否至少匹配一个元素----anyMatch()--->true
检查是否没有匹配的元素----noneMatch()--->false
返回第一个元素----findFirst()--->Person(firstName=Elsdon, lastName=Jaycob, job=Java programmer, gender=male, salary=2000, age=18)
返回流中元素的总数----count()--->12
返回流中最大值----max()--->Person(firstName=Sindy, lastName=Jonie, job=Java programmer, gender=female, salary=35020, age=15)
返回流中最小值----max()--->Person(firstName=Jayden, lastName=Corrina, job=Java programmer, gender=female, salary=345, age=25)

规约


    @Test
public void testStatute(){
/*
* 2. **规约**
* reduce(T identity,BinaryOperator accumulator):可以将流中元素反复结合起来,得到一个值。返回T
* reduce(BinaryOperator accumulator):可以将流中元素反复结合起来,得到一个值。返回Optional
*
* reduce()这个方法经常用到很方便,也更总要,我会再详细的分析总结,这里只做简单认识即可。
*/ //2.1 reduce(T identity,BinaryOperator accumulator):可以将流中元素反复结合起来,得到一个值。返回T
//2.1.1 练习1:计算1-10的自然数的和
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Integer sum = list.stream().reduce(0, Integer::sum);
System.out.println("计算1-10的自然数的和-------reduce(T identity,BinaryOperator accumulator)------>"+sum); //2.2 reduce(BinaryOperator accumulator):可以将流中元素反复结合起来,得到一个值。返回Optional
Integer integers = javaProgrammers.stream().map(Person::getSalary).reduce((e1, e2) -> e1 + e2).get();//lambda表达式
Integer integer = javaProgrammers.stream().map(Person::getSalary).reduce(Integer::sum).get();//使用引用
System.out.println("工资和-------reduce(BinaryOperator accumulator)使用引用------>"+integer);
System.out.println("工资和-------reduce(BinaryOperator accumulator)lambda表达式------>"+integers); }

打印结果:

计算1-10的自然数的和-------reduce(T identity,BinaryOperator accumulator)------>55
工资和-------reduce(BinaryOperator accumulator)使用引用------>64148
工资和-------reduce(BinaryOperator accumulator)lambda表达式------>64148

收集


Collector接口中方法的实现决定了如何对流执行收集的操作(如收集到List、Set、Map)

Collector需要使用Collectors提供实例。

    @Test
public void testSalary(){
/*
* 3. **收集**
* collect(Collector c):将流转换成其他形式。接受一个Collector接口的实现,用于给Stream中元素做汇总的方法
* Collector接口中方法的实现决定了如何对流执行收集的操作(如收集到List、Set、Map)。
* Collector需要使用Collectors提供实例。另外, Collectors实用类提供了很多静态方法,可以方便地创建常见收集器实例,具体方法与实例如下:
toList:返回类型List< T>,作用是把流中元素收集到List
toSet:返回类型Set< T>,作用是把流中元素收集到Set
toCollection:返回类型Collection< T>,作用是把流中元素收集到创建的集合
*
*/ //3.1 collect(Collector c):将流转换成其他形式。返回一个set
System.out.println("将流转换成其他形式。返回一个set-------toSet()------>:");
javaProgrammers.stream().filter(e -> e.getSalary() > 3000).collect(Collectors.toSet()).forEach(System.out::println); //3.2 collect(Collector c):将流转换成其他形式。返回一个list
System.out.println("将流转换成其他形式。返回一个list-------toList()------>:");
javaProgrammers.stream().filter(e -> e.getSalary() > 3000).limit(2).collect(Collectors.toList()).forEach(System.out::println); //3.2 collect(Collector c):将流转换成其他形式。返回一个map
System.out.println("将流转换成其他形式。返回一个map-------toMap()------>:");
javaProgrammers.stream().filter(e -> !e.getFirstName().equals("测试"))
// 注意:key不能重复 toMap()参数一:key 参数二:value 参数三:对key值进行去重,当有重复的key,map中保留第一条重复数据
.collect(Collectors.toMap(Person::getAge,person -> person,(key1, key2) -> key1)) //value 为对象 student -> student jdk1.8返回当前对象,也可以为对象的属性
.forEach((key, value) -> System.out.println("key--"+key+" value--"+value.toString())); }

结束语

完毕!搞明白,读懂,敲会,致此对Stream流也算是有了初步的认识。接下来就慢慢的挖掘吧,打工人。


推荐参考博客:

https://blog.csdn.net/hhq12/article/details/81169145

https://blog.csdn.net/weixin_46744534/article/details/108039064

本文由博客群发一文多发等运营工具平台 OpenWrite 发布

Stream初步认识(一)的更多相关文章

  1. Stream初步应用

    一.什么是stream Stream(流)是一个来自数据源的元素队列并支持聚合操作,数据来源可以从inputstream,数组,集合中获取:聚合操作可以类似SQL语句一样的操作, 比如filter, ...

  2. Java8 stream学习

    Java8初体验(二)Stream语法详解 Java 8 flatMap示例 第一个Stream Demo IDEA里面写Stream有个坑 虽然java文件中没错,但是但编译的时候还是报错了, In ...

  3. ASP.Net MVC开发基础学习笔记:五、区域、模板页与WebAPI初步

    一.区域—麻雀虽小,五脏俱全的迷你MVC项目 1.1 Area的兴起 为了方便大规模网站中的管理大量文件,在ASP.NET MVC 2.0版本中引入了一个新概念—区域(Area). 在项目上右击创建新 ...

  4. ASP.Net MVC开发基础学习笔记(5):区域、模板页与WebAPI初步

    一.区域—麻雀虽小,五脏俱全的迷你MVC项目 1.1 Area的兴起 为了方便大规模网站中的管理大量文件,在ASP.NET MVC 2.0版本中引入了一个新概念—区域(Area). 在项目上右击创建新 ...

  5. 分布式消息系统Kafka初步

    终于可以写kafka的文章了,Mina的相关文章我已经做了索引,在我的博客中置顶了,大家可以方便的找到.从这一篇开始分布式消息系统的入门. 在我们大量使用分布式数据库.分布式计算集群的时候,是否会遇到 ...

  6. CMake初步(2)

    转自:<你所不知的OSG>第一章:CMake初步(2) http://bbs.osgchina.org/forum.php?mod=viewthread&tid=1229& ...

  7. 初步探究java中程序退出、GC垃圾回收时,socket tcp连接的行为

    初步探究java中程序退出.GC垃圾回收时,socket tcp连接的行为 今天在项目开发中需要用到socket tcp连接相关(作为tcp客户端),在思考中发觉需要理清socket主动.被动关闭时发 ...

  8. C++面向对象程序设计之C++的初步知识

    本节内容为学习谭浩强老师编写的<C++面向对象程序设计>的第1章  C++的初步知识  后的个人总结. 在正文开始之前,首先声明,我是Python程序员. 1.2.最简单的C++程序 例1 ...

  9. centos中pipelinedb安装及初步使用

    安装 下载安装包 https://www.pipelinedb.com/download 创建系统文件目录和日志目录 pipelinedb安装 使用非root用户,初始化pipelinedb 修改配置 ...

随机推荐

  1. web应用部署(Tomcat,springboot部署方式)

    转载自:https://www.cnblogs.com/haimishasha/p/10791454.html 核心内容 1.在Tomcat中有四种部署Web应用的方式,分别是: (1)利用Tomca ...

  2. java数据结构-11循环双端队列

    @SuppressWarnings("unchecked") public class CircleDeque<E> { private int front; priv ...

  3. redis简介以及redis集群配置

    简介: redis 是一个高性能的key-value数据库..它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorted set --有序 ...

  4. 「MCOI-03」村国题解

    第二篇题解! 可能是退役之前的最后一篇题解了 (好像总共都只写了两篇) 不说了,讲题: 题面 题意: 有T个数据 有一颗树(保证所有的的节点都是相连的),有n个节点,每个节点都有相应的权值与序号,现在 ...

  5. [Luogu P4178]Tree (点分治+splay)

    题面 传送门:https://www.luogu.org/problemnew/show/P4178 Solution 首先,长成这样的题目一定是淀粉质跑不掉了. 考虑到我们不知道K的大小,我们可以开 ...

  6. Linux下开发环境的搭建(For C++ OIer)

    说句实话,对于OIer来说,Linux真的是个很好的开发平台. 这里既没有游戏的喧嚣,也没有广告的打扰,gcc/g++早已预装,一切已为你准备好......(???)即使对于日常使用,也绰绰有余. 如 ...

  7. 转载-git的安装和使用

    首先是安装和配置,参考了以下博客的内容https://www.cnblogs.com/minRose/p/10286473.html 一.下载地址 https://git-scm.com/downlo ...

  8. Go之发送钉钉和邮箱

    smtp发送邮件 群发两个邮箱,一个163,一个QQ package main import ( "fmt" "net/smtp" "strings& ...

  9. iNeuOS工业互联平台,WEB组态(iNeuView)增加工程视图导入、导出功能,及优化和修复,发布:v3.2.1版本

    目       录 1.      概述... 2 2.      平台演示... 2 3.      导出组态工程文件... 2 4.      导入组态工程文件... 3  1.   概述 iNe ...

  10. JavaSE基础语法学习-异常

    异常 异常指程序运行中出现的不期而至的各种状况,如:文件找不到.网络连接失败.非法参数等. 异常发生在程序运行期间,它影响了正常的程序执行流程. 比如说,你的代码少了一个分号,那么运行出来结果是提示是 ...