java8 集合结合steam操作实例
集合框架介绍:https://www.runoob.com/java/java-collections.html
java8-streams:https://www.runoob.com/java/java8-streams.html
介绍不过说,上面两个链接可以看一下。正常情况下,for循环就够用了,但是有时候你需要对集合遍历多次才能完成的事情,使用steam进行操作,可能只要一次就可以了,而且代码更加简洁明了。部分示例直接复制自菜鸟教程
具体实例
下面是测试的对象和测试用的公共代码
// 用于测试的对象
public class Student {
private Integer id; //学生编号
private String name; // 学生名称
private int age; // 学生年龄
private String cla; // 学生班级
private int sex; // 学生性别 0 女 1 男
public Student(Integer id, String name, int age, String cla, int sex) {
this.id = id;
this.name = name;
this.age = age;
this.cla = cla;
this.sex = sex;
}
... set和get省略
@Override
public String toString() {
return "Student{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", cla='" + cla + '\'' +
", sex=" + sex +
'}';
}
}
// 测试的公共代码
Student student1 = new Student(1, "张1", 12, "一班", 1);
Student student2 = new Student(2, "张2", 13, "一班", 0);
Student student3 = new Student(3, "张3", 12, "一班", 1);
Student student4 = new Student(4, "张4", 14, "二班", 1);
Student student5 = new Student(5, "张5", 13, "二班", 0);
Student student6 = new Student(6, "张6", 12, "二班", 1);
Student student7 = new Student(7, "张7", 11, "三班", 1);
Student student8 = new Student(8, "张8", 12, "三班", 0);
Student student9 = new Student(9, "张9", 13, "三班", 1);
// 异常数据
Student student10 = new Student(9, "张9", 13, null, 1);
Student student11 = new Student(9, "张9", 13, "", 0);
ArrayList<Student> studentList = new ArrayList<>();
studentList.add(student1);
...........
studentList.add(student11);
stream筛选操作
/**
* stream 筛选操作一班用于其他操作前对不符合要求的数据进行过滤,当然筛选功能也是可以单独使用的
* */
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl",null);
List<String> filtered = strings.stream().filter(string -> string != null && !string.isEmpty()).collect(Collectors.toList());
System.out.println(filtered);// 会调用到AbstractCollection的toString方法 [abc, bc, efg, abcd, jkl]
// 过滤学生中的异常数据
List<Student> collect = studentList.stream().filter(student -> student.getCla() != null && !student.getCla().isEmpty()).collect(Collectors.toList());
// 如果过滤条件比较复杂,你可以这么写
List<Student> collect1 = studentList.stream().filter(student -> {
if (student.getCla() != null && !student.getCla().isEmpty()) {
return false;
}
return true;
}).collect(Collectors.toList());
foreach
/**
* foreach遍历功能
* */
Random random = new Random();
IntStream limit = random.ints().limit(10);
// 等价于 int[] ints = limit.toArray();Arrays.stream(ints).forEach(System.out::println);
limit.forEach(System.out::println);
studentList.stream().forEach(System.out::println);
limit
limit 方法用于获取指定数量的流。 以下代码片段使用 limit 方法打印出 10 条数据:
Random random = new Random();
IntStream limit = random.ints().limit(10);
// 等价于 int[] ints = limit.toArray();Arrays.stream(ints).forEach(System.out::println);
limit.forEach(System.out::println);
studentList.stream().forEach(System.out::println);
map
map 方法用于映射每个元素到对应的结果,以下代码片段使用 map 输出了元素对应的平方数:
/**
* 通俗一点讲,就是集合中每个元素计算后获取到另一个元素,添加到新的集合中
* */
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
// 获取对应的平方数
List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
// 下面的代码执行会得到学生年龄的集合
List<Integer> collect2 = studentList.stream().map(i -> i.getAge()).collect(Collectors.toList());
//复杂操作
List<Integer> collect3 = studentList.stream().map(i -> {
return i.getAge() + 1;
}).collect(Collectors.toList());
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();
Collectors
Collectors 类实现了很多归约操作,例如将流转换成集合和聚合元素。Collectors 可用于返回列表或字符串:
groupingBy
/**
* 根据特定字段的不同,将一个集合分成多个集合, 甚至根据多个字段进一步分成多重集合
* 使用时一般要先进行过滤(筛选),避免异常和得到不想要的结果
* */
// 根据性别对学生进行分组, 此处演示,不考虑筛选
Map<Integer, List<Student>> collect4 = studentList.stream().collect(Collectors.groupingBy(Student::getSex));
// 根据复杂的条件进行分组 ,此示例 分组后 map的key为 1 和 2
Map<Integer, List<Student>> collect6 = studentList.stream().collect(Collectors.groupingBy(item -> {
if (item.getAge() > 12) {
return 1;
}
return 2;
}));
// 对学生通过班级分组,再通过性别分组
Map<String, Map<Integer, List<Student>>> collect5 = studentList.stream().filter(student -> student.getCla() != null && !student.getCla().isEmpty()).
collect(Collectors.groupingBy(Student::getCla, Collectors.groupingBy(Student::getSex)));
joining
System.out.println("筛选列表: " + filtered);
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("合并字符串: " + mergedString);
toMap
/**
* Collectors.toMap 将集合中你需要的数据转换成map
* */
// 将list转成map,key为 学生名称, value为学生对象 ,这里由于有学生名称重复,抛出异常一般不这么使用
//Map<String, Student> collect7 = studentList.stream().collect(Collectors.toMap(Student::getName, item -> item));
// 此处和上面相同,但是学生名称重复,会使用后面的学生数据覆盖前面的学生数据
Map<String, Student> collect8 = studentList.stream().collect(Collectors.toMap(Student::getName, item -> item,(key1, key2) -> key2));
// 也可以使用单个字段作为Value
Map<String, String> collect7 = studentList.stream().collect(Collectors.toMap(Student::getName, Student::getCla, (key1, key2) -> key2));
// 除了覆盖,你还可以这么操作
Map<String, String> collect9 = studentList.stream().collect(Collectors.toMap(Student::getName, Student::getCla, (key1, key2) -> key2 + "," + key1));
// 复杂操作
studentList.stream().collect(Collectors.toMap(Student::getName, item -> {
return item.getSex() + "," + item.getId();
}, (key1, key2) -> key2));
统计
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());
public static void testSum() {
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);
// 没有起始值时返回为Optional类型
Optional<Integer> sumOptional = integers.stream().reduce(Integer::sum);
System.out.println(sumOptional.get());
// 可以给一个起始种子值
Integer sumReduce = integers.stream().reduce(-1, Integer::sum);
System.out.println(sumReduce);
//直接用sum方法
Integer sum = integers.stream().mapToInt(i -> i).sum();
System.out.println(sum);
}
public static void testMax() {
//max reduce
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);
Integer maxReduce = integerStream.reduce(Integer.MIN_VALUE, Integer::max);
System.out.println(maxReduce);
// max
Stream<Integer> integerStream1 = Stream.of(1, 2, 3, 4, 5);
OptionalInt max = integerStream1.mapToInt(i -> i).max();
System.out.println(max.getAsInt());
}
public static void testReduce() {
Stream<Integer> stream = Arrays.stream(new Integer[]{1, 2, null});
//求集合元素只和
Integer result = stream.filter(item -> {
return item != null && item !=1 && item != 2;
}).reduce(0, Integer::max);
System.out.println(result);
stream = Arrays.stream(new Integer[]{1, 2, 3, 4, 5, 6, 7});
//求和
stream.reduce((i, j) -> i + j).ifPresent(System.out::println);
stream = Arrays.stream(new Integer[]{1, 2, 3, 4, 5, 6, 7});
//求最大值
stream.reduce(Integer::max).ifPresent(System.out::println);
stream = Arrays.stream(new Integer[]{1, 2, 3, 4, 5, 6, 7});
//求最小值
stream.reduce(Integer::min).ifPresent(System.out::println);
stream = Arrays.stream(new Integer[]{1, 2, 3, 4, 5, 6, 7});
//做逻辑
stream.reduce((i, j) -> i > j ? j : i).ifPresent(System.out::println);
stream = Arrays.stream(new Integer[]{1, 2, 3, 4, 5, 6, 7});
//求逻辑求乘机
int result2 = stream.filter(i -> i % 2 == 0).reduce(1, (i, j) ->{
return i * j;
});
Optional.of(result2).ifPresent(System.out::println);
}
git操作
1、 下拉指定分支
git clone -b 分支名 git地址
2、git版本控制目录,删除不需要的文件(这里删除所有)
3、 添加忽略文件,提交文件到暂存区,推送到远程
git status -s 查看文件状态
git add .
git commit -m 'commit'
git push
4、 添加新的项目文件
git add .
git commit -m 'commit'
git push
集合拆分
// 代码来自网络(不记得来自那篇博文了), 亲测有效,可以结合steam操作尝试更简便的实现
public static <T> List<List<T>> split(List<T> resList,int count){
if(resList==null ||count<1)
return null ;
List<List<T>> ret=new ArrayList<List<T>>();
int size=resList.size();
if(size<=count){ //数据量不足count指定的大小
ret.add(resList);
}else{
int pre=size/count;
int last=size%count;
// 前面pre个集合,每个大小都是count个元素
for(int i=0;i<pre;i++){
List<T> itemList=new ArrayList<T>();
for(int j=0;j<count;j++){
itemList.add(resList.get(i*count+j));
}
ret.add(itemList);
}
// last的进行处理
if(last>0){
List<T> itemList=new ArrayList<T>();
for(int i=0;i<last;i++){
itemList.add(resList.get(pre*count+i));
}
ret.add(itemList);
}
}
return ret;
}
需要引入guava
// 例:将集合:list 分割成每个集合25条数据的集合。
List<String> list = new ArrayList<>(100);
for (int i = 0; i < 100; i++) {
list.add("1");
}
List<List<String>> partition = Lists.partition(list , 25);
for (List<String> data : partition) {
//执行插入
System.out.println(data.size());
}
orcale 批量插入操作
你会发现批量操作缺失快很多
// 以下批量操作,操作的数据量不能过大, 毕竟数据传输是有大小限制的, 所以你可能需要对集合进行拆分,拆分注意了,很容易出错,漏了最后一部分
int insertBatch(@Param("studentList") List<Student> studentList);
<insert id="insertBatch" useGeneratedKeys="false" parameterType="java.util.List">
INSERT ALL
<foreach collection="studentList" item="student">
into student (id, name) VALUES
(#{student.id},#{student.name})
</foreach>
SELECT 1 FROM DUAL
</insert>