目录

· 概况

· 切片(Slicing)

· 映射(Mapping)

· 匹配(Matching)

· 查找(Finding)

· 归约(Reducing)

· 排序(Sorting)

· 数值流(Numeric streams)

· 原始类型流(Primitive stream)

· 数值范围(Numeric ranges)

· 构建流

· 由值创建流

· 由数组创建流

· 由文件生成流

· 由函数生成流(创建无限流)

· collect()高级用法

· 分组(Grouping)

· 分区(Partitioning)

· 并行流


概况

1. Stream API:以声明性方式处理数据集合,即说明想要完成什么(比如筛选热量低的菜肴)而不是说明如何实现一个操作(利用循环和if条件等控制流语句)。

2. Stream API特点

a) 流水线:很多流操作本身会返回一个流,这样多个操作就可以链接起来,形成一个大的流水线。这让可实现延迟和短路优化。

b) 内部迭代:与使用迭代器显式迭代的集合不同,流的迭代操作是在背后进行的。

3. Stream(流):从支持数据处理操作的源生成的元素序列(A sequence of elements from a source that supports data processing operations)。

a) 元素序列:与集合类似,流也提供了一个接口(java.util.stream.Stream),可以访问特定元素类型的一组有序值。因为集合是数据结构,所以它的主要目的是以特定的时间/空间复杂度存储和访问元素(如ArrayList、LinkedList);但流的目的在于表达计算,比如filter、sorted和map。

b) 源:流会使用一个提供数据的源,如集合、数组或输入/输出。注意,从有序集合生成流时会保留原有的顺序。

c) 数据处理操作:流的数据处理功能支持类似于数据库的操作,以及函数式编程语言中的常用操作,如filter、map、reduce、find、match、sort等。流操作可以顺序执行,也可并行执行。

4. 流操作分类

a) 中间操作(Intermediate Operations):可以连接起来的流操作,并不会生成任何结果。

b) 终端操作(Terminal Operations):关闭流的操作,处理流水线以返回结果。

c) 常用中间操作

操作

返回类型

操作参数

函数描述符

filter

Stream<T>

Predicate<T>

T -> boolean

map

Stream<R>

Function<T, R>

T -> R

limit

Stream<T>

sorted

Stream<T>

Comparator<T>

(T, T) -> R

distinct

Stream<T>

 

d) 常用终端操作

操作

目的

forEach

消费流中的每个元素并对其应用Lambda。这一操作返回void。

count

返回流中元素的个数。这一操作返回long。

collect

把流归约成一个集合,比如List、Map甚至是Integer。

5. 举例

a) Dish.java(后续举例将多次使用到该类)

 public class Dish {
private final String name;
private final boolean vegetarian;
private final int calories;
private final Type type; public enum Type {MEAT, FISH, OTHER} public Dish(String name, boolean vegetarian, int calories, Type type) {
this.name = name;
this.vegetarian = vegetarian;
this.calories = calories;
this.type = type;
} public String getName() {
return name;
} public boolean isVegetarian() {
return vegetarian;
} public int getCalories() {
return calories;
} public Type getType() {
return type;
} @Override
public String toString() {
return name;
} }

b) DishUtils.java(后续举例将多次使用到该类)

 import java.util.Arrays;
import java.util.List; public class DishUtils { public static List<Dish> makeMenu() {
return Arrays.asList(
new Dish("pork", false, 800, Dish.Type.MEAT),
new Dish("beef", false, 700, Dish.Type.MEAT),
new Dish("chicken", false, 400, Dish.Type.MEAT),
new Dish("french fries", true, 530, Dish.Type.OTHER),
new Dish("rice", true, 350, Dish.Type.OTHER),
new Dish("season fruit", true, 120, Dish.Type.OTHER),
new Dish("pizza", true, 550, Dish.Type.OTHER),
new Dish("prawns", false, 300, Dish.Type.FISH),
new Dish("salmon", false, 450, Dish.Type.FISH));
} public static <T> void printList(List<T> list) {
for (T i : list) {
System.out.println(i);
}
} }

c) Test.java

 import java.util.List;

 import static java.util.stream.Collectors.toList;

 public class Test {

     public static void main(String[] args) {
List<String> names = DishUtils.makeMenu().stream() // 获取流
.filter(d -> d.getCalories() > 300) // 中间操作,选出高热量菜
.map(Dish::getName) // 中间操作,获取菜名
.limit(3) // 中间操作,选出前三
.collect(toList()); // 终端操作,将结果保存在List中
DishUtils.printList(names); DishUtils.makeMenu().stream()
.filter(d -> d.getCalories() > 300)
.map(Dish::getName)
.limit(3)
.forEach(System.out::println); // 遍历并打印
} }

d) 示意图

筛选(Filtering)

1. 筛选相关方法

a) filter()方法:使用Predicate筛选流中元素。

b) distinct()方法:调用流中元素的hashCode()和equals()方法去重元素。

2. 举例

 import java.util.Arrays;
import java.util.List;
import static java.util.stream.Collectors.toList;
// filter()方法
List<Dish> vegetarianMenu = DishUtils.makeMenu().stream()
.filter(Dish::isVegetarian)
.collect(toList());
DishUtils.printList(vegetarianMenu);
System.out.println("-----");
// distinct()方法
List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
numbers.stream()
.filter(i -> i % 2 == 0)
.distinct()
.forEach(System.out::println);

切片(Slicing)

1. 切片相关方法

a) limit()方法:返回一个不超过给定长度的流。

b) skip()方法:返回一个扔掉了前n个元素的流。如果流中元素不足n个,则返回一个空流。

2. 举例

 import java.util.List;
import static java.util.stream.Collectors.toList;
// limit()方法
List<Dish> dishes1 = DishUtils.makeMenu().stream()
.filter(d -> d.getCalories() > 300)
.limit(3)
.collect(toList());
DishUtils.printList(dishes1);
System.out.println("-----");
// skip()方法
List<Dish> dishes2 = DishUtils.makeMenu().stream()
.filter(d -> d.getCalories() > 300)
.skip(2)
.collect(toList());
DishUtils.printList(dishes2);

映射(Mapping)

1. 映射相关方法

a) map()方法:接受一个函数作为参数,该函数用于将每个元素映射成一个新的元素。

b) flatMap()方法:接受一个函数作为参数,该函数用于将每个数组元素映射成新的扁平化流。

c) 注意:map()、flatMap()方法都不会修改原元素。

2. 举例

 import java.util.Arrays;
import java.util.List;
import static java.util.stream.Collectors.toList;
// map()方法
List<Integer> dishNameLengths = DishUtils.makeMenu().stream()
.map(Dish::getName)
.map(String::length)
.collect(toList());
DishUtils.printList(dishNameLengths);
System.out.println("-----");
// flatMap()方法
String[] arrayOfWords = {"Goodbye", "World"};
Arrays.stream(arrayOfWords)
.map(w -> w.split("")) // 将每个单词转换为由其字母构成的数组
.flatMap(Arrays::stream) // 将各个生成流扁平化为单个流
.distinct() // 去重
.forEach(System.out::println);

匹配(Matching)

1. 匹配相关方法

a) anyMatch()方法:检查流中是否有一个元素能匹配给定的Predicate。

b) allMatch()方法:检查流中是否所有元素能匹配给定的Predicate。

c) noneMatch()方法:检查流中是否所有元素都不匹配给定的Predicate。

2. 举例

 // anyMatch()方法
if (DishUtils.makeMenu().stream().anyMatch(Dish::isVegetarian)) {
System.out.println("The menu is (somewhat) vegetarian friendly!!");
}
// allMatch()方法
boolean isHealthy1 = DishUtils.makeMenu().stream()
.allMatch(d -> d.getCalories() < 1000);
System.out.println(isHealthy1);
// noneMatch()方法
boolean isHealthy2 = DishUtils.makeMenu().stream()
.noneMatch(d -> d.getCalories() >= 1000);
System.out.println(isHealthy2);

查找(Finding)

1. 查找相关方法

a) findAny()方法:返回当前流中的任意元素,返回类型为java.util.Optional(Java 8用于解决NullPointerException的新类)。

b) findFirst()方法:与findAny()方法类似,区别在于返回第一个元素。

2. 举例

 import java.util.Arrays;
import java.util.List;
import java.util.Optional;
// findAny()方法
Optional<Dish> dish = DishUtils.makeMenu().stream()
.filter(Dish::isVegetarian)
.findAny();
System.out.println(dish.get()); // french fries
// findFirst()方法
List<Integer> someNumbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> firstSquareDivisibleByThree = someNumbers.stream()
.map(x -> x * x)
.filter(x -> x % 3 == 0)
.findFirst(); //
System.out.println(firstSquareDivisibleByThree.get());

归约(Reducing)

1. 归约相关方法

a) reduce()方法:把一个流中的元素组合起来,也叫折叠(fold)。

i. 如果指定初始值,则直接返回归约结果值。

ii. 如果不指定初始值,则返回Optional。

2. 举例

 import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
List<Integer> numbers = new ArrayList<>();
for (int n = 1; n <= 100; n++) {
numbers.add(n);
}
// 元素求和
int sum1 = numbers.stream().reduce(0, (a, b) -> a + b); // 指定初始值0
System.out.println(sum1);
Optional<Integer> sum2 = numbers.stream().reduce((a, b) -> a + b); // 不指定初始值0
System.out.println(sum2);
int sum3 = numbers.stream().reduce(0, Integer::sum); // 方法引用
System.out.println(sum3);
// 最大值
Optional<Integer> max1 = numbers.stream().reduce((a, b) -> a < b ? b : a); // Lambda表达式
System.out.println(max1);
Optional<Integer> max2 = numbers.stream().reduce(Integer::max); // 方法引用
System.out.println(max2);
// 统计个数
int count1 = DishUtils.makeMenu().stream()
.map(d -> 1)
.reduce(0, (a, b) -> a + b); // MapReduce编程模型,更易并行化
System.out.println(count1);
long count2 = DishUtils.makeMenu().stream().count();
System.out.println(count2);

排序(Sorting)

1. 排序相关方法

a) sorted()方法:根据指定的java.util.Comparator规则排序。

2. 举例

 import static java.util.Comparator.comparing;
DishUtils.makeMenu().stream()
.sorted(comparing(Dish::getCalories))
.forEach(System.out::println);

数值流(Numeric streams)

原始类型流(Primitive stream)

1. 使用目的:避免自动装箱带来的开销。

2. 相关方法

a) mapToInt():将流转换为原始类型流IntStream。

b) mapToDouble():将流转换为原始类型流DoubleStream。

c) mapToLong():将流转换为原始类型流LongStream。

d) boxed():将原始类型流转换为对象流。

3. Optional的原始类型版本:OptionalInt、OptionalDouble和OptionalLong。

4. 举例

 import java.util.OptionalInt;
import java.util.stream.IntStream;
import java.util.stream.Stream;
// 映射到数值流
int calories = DishUtils.makeMenu().stream() // 返回Stream<Dish>
.mapToInt(Dish::getCalories) // 返回IntStream
.sum();
System.out.println(calories);
// 转换回对象流
IntStream intStream = DishUtils.makeMenu().stream().mapToInt(Dish::getCalories); // 将Stream 转换为数值流
Stream<Integer> stream = intStream.boxed(); // 将数值流转换为Stream
// OptionalInt
OptionalInt maxCalories = DishUtils.makeMenu().stream()
.mapToInt(Dish::getCalories)
.max();
int max = maxCalories.orElse(1); // 如果没有最大值的话,显式提供一个默认最大值
System.out.println(max);

数值范围(Numeric ranges)

1. 数值范围相关方法

a) range()方法:生成起始值到结束值范围的数值,不包含结束值。

b) rangeClosed()方法:生成起始值到结束值范围的数值,包含结束值。

2. 举例

 import java.util.stream.IntStream;
IntStream.range(1, 5).forEach(System.out::println); // 1~4
IntStream.rangeClosed(1, 5).forEach(System.out::println); // 1~5

构建流

由值创建流

1. 举例

a) Stream.of()方法

 import java.util.stream.Stream;
Stream<String> stream = Stream.of("Java 8 ", "Lambdas ", "In ", "Action");
stream.map(String::toUpperCase).forEach(System.out::println);

b) 空流

 import java.util.stream.Stream;
Stream<String> emptyStream = Stream.empty();

由数组创建流

1. 举例

 int[] numbers = {2, 3, 5, 7, 11, 13};
int sum = Arrays.stream(numbers).sum();
System.out.println(sum); //

由文件生成流

1. 举例

 try (Stream<String> lines = Files.lines(Paths.get("data.txt"), Charset.defaultCharset())) {
long uniqueWords = lines.flatMap(line -> Arrays.stream(line.split(" ")))
.distinct()
.count();
System.out.println(uniqueWords);
} catch (IOException e) {
e.printStackTrace();
}

由函数生成流(创建无限流)

1. 无限流:没有固定大小的流。

2. 相关方法

a) Stream.iterate()方法:生成无限流,其初始值为第1个参数,下一个值由第2个参数的Lambda表达式生成。

b) Stream.generate()方法:生成无限流,其值由参数的Lambda表达式生成。

3. 注意:一般,应该使用limit(n)对无限流加以限制,以避免生成无穷多个值。

4. 举例

 Stream.iterate(0, n -> n + 2)
.limit(5)
.forEach(System.out::println); // 0 2 4 6 8
Stream.generate(Math::random)
.limit(5)
.forEach(System.out::println);

collect()高级用法

归约和汇总(Reducing and summarizing)

1. 举例

a) 按元素某字段查找最大值

 import java.util.Comparator;
import java.util.Optional;
import static java.util.stream.Collectors.maxBy;
Comparator<Dish> dishCaloriesComparator = Comparator.comparingInt(Dish::getCalories);
Optional<Dish> mostCalorieDish = DishUtils.makeMenu().stream()
.collect(maxBy(dishCaloriesComparator));
System.out.println(mostCalorieDish);

b) 按元素某字段求和

 import static java.util.stream.Collectors.summingInt;
int totalCalories = DishUtils.makeMenu().stream().collect(summingInt(Dish::getCalories));
System.out.println(totalCalories);

c) 按元素某字段求平均值

 import static java.util.stream.Collectors.averagingInt;
double avgCalories = DishUtils.makeMenu().stream().collect(averagingInt(Dish::getCalories));
System.out.println(avgCalories);

d) 连接字符串

 import static java.util.stream.Collectors.joining;
String shortMenu = DishUtils.makeMenu().stream().map(Dish::getName).collect(joining(", "));
System.out.println(shortMenu);

e) 广义归约

 // 所有热量求和
import static java.util.stream.Collectors.reducing;
// i.e.
// int totalCalories = DishUtils.makeMenu().stream()
// .mapToInt(Dish::getCalories) // 转换函数
// .reduce(0, Integer::sum); // 初始值、累积函数
int totalCalories = DishUtils.makeMenu().stream()
.collect(reducing(
0, // 初始值
Dish::getCalories, // 转换函数
Integer::sum)); // 累积函数
System.out.println(totalCalories);

分组(Grouping)

1. 分组:类似SQL语句的group by,区别在于这里的分组可聚合(即SQL的聚合函数),也可不聚合。

2. 举例

a) 简单分组

 Map<Dish.Type, List<Dish>> dishesByType = DishUtils.makeMenu().stream()
.collect(groupingBy(Dish::getType));
System.out.println(dishesByType); // {FISH=[prawns, salmon], MEAT=[pork, beef, chicken], OTHER=[french fries, rice, season fruit, pizza]}

b) 复杂分组

 import static java.util.stream.Collectors.groupingBy;
public enum CaloricLevel {DIET, NORMAL, FAT}
Map<CaloricLevel, List<Dish>> dishesByCaloricLevel = DishUtils.makeMenu().stream().collect(
groupingBy(dish -> {
if (dish.getCalories() <= 400) return CaloricLevel.DIET;
else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL;
else return CaloricLevel.FAT;
}));
System.out.println(dishesByCaloricLevel); // {NORMAL=[beef, french fries, pizza, salmon], DIET=[chicken, rice, season fruit, prawns], FAT=[pork]}

c) 多级分组

 import static java.util.stream.Collectors.groupingBy;
public enum CaloricLevel {DIET, NORMAL, FAT}
Map<Dish.Type, Map<CaloricLevel, List<Dish>>> dishesByTypeCaloricLevel = DishUtils.makeMenu().stream().collect(
groupingBy(Dish::getType, // 一级分类函数
groupingBy(dish -> { // 二级分类函数
if (dish.getCalories() <= 400) return CaloricLevel.DIET;
else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL;
else return CaloricLevel.FAT;
})
)
);
System.out.println(dishesByTypeCaloricLevel);
// {FISH={NORMAL=[salmon], DIET=[prawns]}, MEAT={NORMAL=[beef], DIET=[chicken], FAT=[pork]}, OTHER={NORMAL=[french fries, pizza], DIET=[rice, season fruit]}}

d) 分组聚合

 import static java.util.Comparator.comparingInt;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.counting;
Map<Dish.Type, Long> typesCount = DishUtils.makeMenu().stream()
.collect(groupingBy(Dish::getType, counting()));
System.out.println(typesCount); // {FISH=2, MEAT=3, OTHER=4} Map<Dish.Type, Optional<Dish>> mostCaloricByType1 = DishUtils.makeMenu().stream()
.collect(groupingBy(Dish::getType, maxBy(comparingInt(Dish::getCalories))));
System.out.println(mostCaloricByType1); // {FISH=Optional[salmon], MEAT=Optional[pork], OTHER=Optional[pizza]} Map<Dish.Type, Dish> mostCaloricByType2 = DishUtils.makeMenu().stream()
.collect(groupingBy(Dish::getType, // 分类函数
collectingAndThen(
maxBy(comparingInt(Dish::getCalories)), // 包装后的收集器
Optional::get))); // 转换函数
System.out.println(mostCaloricByType2); // {FISH=salmon, MEAT=pork, OTHER=pizza}

分区(Partitioning)

1. 分区:分区是分组的特殊情况,即根据Predicate<T>分组为true和false两组,因此分组后的Map的Key是Boolean类型。

2. 举例

 import java.util.List;
import java.util.Map;
import java.util.Optional;
import static java.util.Comparator.comparingInt;
import static java.util.stream.Collectors.*;
Map<Boolean, List<Dish>> partitionedMenu = DishUtils.makeMenu().stream()
.collect(partitioningBy(Dish::isVegetarian));
System.out.println(partitionedMenu);
// {false=[pork, beef, chicken, prawns, salmon], true=[french fries, rice, season fruit, pizza]} Map<Boolean, Map<Dish.Type, List<Dish>>> vegetarianDishesByType = DishUtils.makeMenu().stream()
.collect(partitioningBy(Dish::isVegetarian, groupingBy(Dish::getType)));
System.out.println(vegetarianDishesByType);
// {false={FISH=[prawns, salmon], MEAT=[pork, beef, chicken]}, true={OTHER=[french fries, rice, season fruit, pizza]}} Map<Boolean, Dish> mostCaloricPartitionedByVegetarian = DishUtils.makeMenu().stream()
.collect(partitioningBy(Dish::isVegetarian, collectingAndThen(maxBy(comparingInt(Dish::getCalories)), Optional::get)));
System.out.println(mostCaloricPartitionedByVegetarian);
// {false=pork, true=pizza}

并行流

1. 并行流:一个把内容分成多个数据块,并用不同的线程分别处理每个数据块的流。

2. 并行流相关方法

a) parallel()方法:将顺序流转换为并行流。

b) sequential()方法:将并行流转换为顺序流。

c) 以上两方法并没有对流本身有任何实际的变化,只是在内部设了一个boolean标志,表示让调用parallel()/sequential()之后进行的所有操作都并行/顺序执行。

3. 并行流原理:并行流内部默认使用ForkJoinPool,其默认的线程数为CPU核数(通过Runtime.getRuntime().availableProcessors()获取),同时支持通过系统属性设置(全局),比如:

System.setProperty('java.util.concurrent.ForkJoinPool.common.parallelism','12');

4. 何时并行流更有效?

a) 实测:在待运行的特定机器上,分别用顺序流和并行流做基准测试性能。

b) 注意装/拆箱:自动装箱和拆箱会大大降低性能,应避免。

c) 某些操作性能并行流比顺序流差:比如limit()和findFirst(),因为在并行流上执行代价较大。

d) 计算流操作流水线的总成本:设N是要处理的元素的总数,Q是一个元素通过流水线的大致处理成本,则N*Q就是这个对成本的一个粗略的定性估计。Q值较高就意味着使用并行流时性能好的可能性比较大。

e) 数据量较小时并行流比顺序流性能差:因为并行化会有额外开销。

f) 流背后的数据结构是否易于分解:见下表。

数据结构

可分解性

ArrayList

极佳

LinkedList

IntStream.range

极佳

Stream.iterate

HashSet

TreeSet

g) 流自身特点、流水线的中间操作修改流的方式,都可能会改变分解过程的性能:比如未执行筛选操作时,流被分成大小差不多的几部分,此时并行执行效率很高;但执行筛选操作后,可能导致这几部分大小相差较大,此时并行执行效率就较低。

h) 终端操作合并步骤的代价:如果该步骤代价很大,那么合并每个子流产生的部分结果所付出的代价就可能会超出通过并行流得到的性能提升。

5. 举例

 // 顺序流
long sum1 = Stream.iterate(1L, i -> i + 1)
.limit(8)
.reduce(0L, Long::sum);
System.out.println(sum1);
// 并行流
long sum2 = Stream.iterate(1L, i -> i + 1)
.limit(8)
.parallel()
.reduce(0L, Long::sum);
System.out.println(sum2);

作者:netoxi
出处:http://www.cnblogs.com/netoxi
本文版权归作者和博客园共有,欢迎转载,未经同意须保留此段声明,且在文章页面明显位置给出原文连接。欢迎指正与交流。

3分钟看完Java 8——史上最强Java 8新特性总结之第二篇 Stream API的更多相关文章

  1. 3分钟看完Java 8——史上最强Java 8新特性总结之第四篇 其他新特性

    目录 · 默认方法和静态方法 · 初步理解 · 应用模式 · 优先级问题 · Optional · CompletableFuture · 基本用法 · CompletableFuture与Strea ...

  2. 3分钟看完Java 8——史上最强Java 8新特性总结之第三篇 函数式编程技巧

    目录 · 改写设计模式 · 策略模式(Strategy Pattern) · 模板方法模式(Template Method Pattern) · 观察者模式(Observer Pattern) · 责 ...

  3. 3分钟看完Java 8——史上最强Java 8新特性总结之第一篇 函数式编程基础

    目录 · 行为参数化 · Lambda表达式 · 概况 · 函数式接口 · 类型推断 · 使用外层变量 · 方法引用 · 复合Lambda表达式 行为参数化 1. 理解函数式编程要先理解行为参数化. ...

  4. 史上最强Java NIO入门:担心从入门到放弃的,请读这篇!

    本文原题“<NIO 入门>,作者为“Gregory M. Travis”,他是<JDK 1.4 Tutorial>等书籍的作者. 1.引言 Java NIO是Java 1.4版 ...

  5. 金九银十,史上最强 Java 面试题整理。

    以下会重新整理所有 Java 系列面试题答案.及各大互联网公司的面试经验,会从以下几个方面汇总,本文会长期更新. Java 面试篇 史上最全 Java 面试题,带全部答案 史上最全 69 道 Spri ...

  6. Java 8新特性之旅:使用Stream API处理集合

    在这篇“Java 8新特性教程”系列文章中,我们会深入解释,并通过代码来展示,如何通过流来遍历集合,如何从集合和数组来创建流,以及怎么聚合流的值. 在之前的文章“遍历.过滤.处理集合及使用Lambda ...

  7. Java 8新特性(二):Stream API

    本篇文章继续介绍Java 8的另一个新特性--Stream API.新增的Stream API与InputStream和OutputStream是完全不同的概念,Stream API是对Java中集合 ...

  8. 【Java8新特性】关于Java8的Stream API,看这一篇就够了!!

    写在前面 Java8中有两大最为重要的改变.第一个是 Lambda 表达式:另外一个则是 Stream API(java.util.stream.*) ,那什么是Stream API呢?Java8中的 ...

  9. 史上最强Java开发环境搭建

    在项目产品开发中,开发环境搭建是软件开发的首要阶段,也是必须阶段,只有开发环境搭建好了,方可进行开发,良好的开发环境搭建,为后续的开发工作带来极大便利. 对于大公司来说,软件开发环境搭建工作一般是由运 ...

随机推荐

  1. 3.11formdata的使用

    var formData = new FormData(); formData.append('files[]',document.getElementById("file").f ...

  2. 数据结构C语言版-队列

    #include <stdlib.h> #include <stdio.h> #include <iostream> using namespace std; ty ...

  3. Shell的特殊变量

    在Shell里存在的一些特殊变量:$!.$@.$#.$$.$*.$0.$n.$_.$? [root@shell ~]# sh shell.sh aaa bbb ccc$0 获取当前执行的shell脚本 ...

  4. ntile函数

    ntile函数可以对序号进行分组处理,将有序分区中的行分发到指定数目的组中. 各个组有编号,编号从一开始. 对于每一个行,ntile 将返回此行所属的组的编号.这就相当于将查询出来的记录集放到指定长度 ...

  5. mysql实现多实例

    > mariadb安装    yum install mariadb-server > 创建相关目录,及设置权限    mkdir /mysqldb; mkdir /mysqldb/{33 ...

  6. idea 新建项目上传至git(coding)

    一.新建项目 1.改为git版本 2.出现如下框 选择Git 3.新建一个.gitignore file (Git) 4.勾掉一些不需要的 5.出现如下框 5.1.如果不知道.gitignore fi ...

  7. 运维工具pssh和pdsh安装和使用

    1. pssh安装与使用 1.1 pssh安装 [root@server]# wget http://peak.telecommunity.com/dist/ez_setup.py [root@ser ...

  8. python基础自学 第二天

    注释 分类 单行注释 多行注释 作用 使用自己熟悉的语言,在程序中对某些代码进行标注说明,增强程序可读性 单行注释(行注释) 以 # 开头,#右边所有的东西就被当成说明文字,而不是要执行的程序,只是说 ...

  9. 暴走Python之运算符与条件语句

    本文原创作者:LoneliNess,本文属i春秋原创奖励计划,未经许可禁止转载   本文来源:i春秋学院   i春秋(ichunqiu.com)网络安全平台能提供专业的网络安全技术.网络渗透技术.网络 ...

  10. 在react中使用less(官方做法)

    概述 在用create-react-app搭建react app的时候,原生并不支持less,只支持css.不过create-react-app官方给了一种方法使用less,我觉得很有用,记录下来,供 ...