Java++:JDK8 流操作

1):对象 List<User> 转 Map<String,Object>

案例如下:

 public class User {
 
    private Integer id;
    private String age;

    User(Integer id, String age) {
        this.id = id;
        this.age = age;
    }

}

List<User> userList = new ArrayList<User>() {{
    add(new User(1, "1111"));
    add(new User(1, "1111"));
    add(new User(2, "2222"));
}};

// 方式一(不推荐):遇到重复的 id 值。  会抛异常 java.lang.IllegalStateException: Duplicate key User
Map<Integer, User> maps = userList.stream().collect(Collectors.toMap(User::getId, Function.identity()));

// 方式二:(推荐)
Map<Integer, User> maps = userList.stream().collect(Collectors.toMap(User::getId, Function.identity(), (key1, key2) -> key2));

2):================START=======================

测试数据如下:

public class TestStreamModel implements Serializable {

    private int id;
    private String name;
    private int grade;
    private int classes;
    private double score;
    public TestStreamModel(int id, String name, int grade, int classes, double score) {
        this.id = id;
        this.name = name;
        this.grade = grade;
        this.classes = classes;
        this.score = score;
    }
    
    get|set...省略
    
    @Override
    public String toString() {
        return "TestStreamModel{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", grade=" + grade +
                ", classes=" + classes +
                ", score=" + score +
                '}';
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        TestStreamModel that = (TestStreamModel) o;
        return id == that.id &&
                grade == that.grade &&
                classes == that.classes &&
                Double.compare(that.score, score) == 0 &&
                Objects.equals(name, that.name);
    }
    @Override
    public int hashCode() {

        return Objects.hash(id, name, grade, classes, score);
    }
}




// 初始化数据
List<TestStreamModel> list = new ArrayList<TestStreamModel>() {{
    add(new TestStreamModel(1, "李四", 1, 1, 60));
    add(new TestStreamModel(2, "张三", 1, 1, 80));
    add(new TestStreamModel(3, "王二麻子", 1, 2, 90));
    add(new TestStreamModel(4, "王五", 1, 3, 59.5));
    add(new TestStreamModel(5, "小红", 2, 2, 99));
    add(new TestStreamModel(6, "小白", 2, 1, 88.8));
    add(new TestStreamModel(7, "小黑", 2, 2, 45));
    add(new TestStreamModel(8, "小明", 1, 1, 79.5));
    add(new TestStreamModel(8, "小明", 1, 1, 79.5));
}};
测试数据

2-1):去重-去除重复对象(每个属性的值都一样的),需要注意的是要先重写对象 TestStreamModel 的 equals 和 hashCode 方法

System.out.println("集合数量:" + list.size() + "-->每个属性的值都一样的-->去重前:" + list);
List<TestStreamModel> distinctList = list.stream().distinct().collect(Collectors.toList());
System.out.println("集合数量:" + distinctList.size() + "-->每个属性的值都一样的-->去重后:" + distinctList);

2-2):去重,去除重复对象(根据对象其中一个属性进行去重)

ArrayList<TestStreamModel> collect = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(TestStreamModel::getId))), ArrayList::new));

2-3):排序,按id升续排列,如果要降续则改成:(a, b) -> b.getId() - a.getId(); a和b都是变量名(可以按自己意愿取名字),都是list中的对象的实例

List<TestStreamModel> sortList = list.stream().sorted((a, b) -> a.getId() - b.getId()).collect(Collectors.toList());

多字段排序:

List<Ticket> list = new ArrayList<Ticket>() {{
    add(new Ticket("2023-05-26 15:00:00", 1));
    add(new Ticket("2023-05-26 15:00:00", 3));
    add(new Ticket("2023-05-26 15:00:00", 2));
    add(new Ticket("2023-05-26 15:00:00", 4));
    add(new Ticket("2023-05-27 15:00:00", 5));
    add(new Ticket("2023-05-28 15:00:00", 7));
}};

List<Ticket> sortList = list.stream()
        .sorted(Comparator.comparing(Ticket::getExEndTime, Comparator.reverseOrder())
                .thenComparing(e -> {
                    return Integer.valueOf(e.getNum());
                }, Comparator.reverseOrder())
        )
        .collect(Collectors.toList());

LOGGER.info("--:{}", list);

class Ticket {

    private String exEndTime;
    private Integer num;

    public Ticket(String exEndTime, Integer num) {
        this.exEndTime = exEndTime;
        this.num = num;
    }

    public String getExEndTime() {
        return exEndTime;
    }

    public void setExEndTime(String exEndTime) {
        this.exEndTime = exEndTime;
    }

    public Integer getNum() {
        return num;
    }

    public void setNum(Integer num) {
        this.num = num;
    }

    @Override
    public String toString() {
        return JSON.toJSONString(this);
    }
}

2-4):过滤,按照自己的需求来筛选list中的数据,比如我筛选出不及格的(小于60分)的人,t为实例

List<TestStreamModel> filterList = list.stream().filter(t -> t.getScore() < 60).collect(Collectors.toList());

2-5):Map, 提取对象中的某一元素,例子中我取的是每个人的name,注意list中类型对应,如果取的是id或者班级,就应该是integer类型

List<String> mapList = list.stream().map(t -> t.getName()).collect(Collectors.toList());

2-6):统计,统计所有人分数的和, 主要我设置的分数属性是double类型的,所以用mapToDouble,如果是int类型的,则需要用mapToInt

double sum = list.stream().mapToDouble(t -> t.getScore()).sum();
int count = list.stream().mapToInt(t -> t.getId()).sum();

2-7):分组, 按照字段中某个属性将list分组

Map<Integer, List<TestStreamModel>> map = list.stream().collect(Collectors.groupingBy(t -> t.getGrade()));
System.out.println("按年级分组" + map);
/*然后再对map处理,这样就方便取出自己要的数据*/
for (Map.Entry<Integer, List<TestStreamModel>> entry : map.entrySet()) {
    System.out.println("key:" + entry.getKey());
    System.out.println("value:" + entry.getValue());
}

2-8):多重分组,先按年级分组,再按班级分组

Map<Integer/*年级id*/, Map<Integer/*班级id*/, List<TestStreamModel>>> groupMap = list.stream().collect(Collectors.groupingBy(t -> t.getGrade(), Collectors.groupingBy(t -> t.getClasses())));
System.out.println("按照年级再按班级分组:" + groupMap);
System.out.println("取出一年级一班的list:" + groupMap.get(1).get(1));

2-9):多重分组,一般多重分组后都是为了统计,比如说统计每个年级,每个班的总分数

Map<Integer/*年级id*/, Map<Integer/*班级id*/, Double>> sumMap = list.stream().collect(Collectors.groupingBy(t -> t.getGrade(), Collectors.groupingBy(t -> t.getClasses(), Collectors.summingDouble(t -> t.getScore()))));
System.out.println(sumMap);
System.out.println("取出一年级一班的总分:" + sumMap.get(1).get(1));

2-10):多重分组,一般多重分组后都是为了统计,比如说统计每个年级,每个班的总分数

Map<Integer/*年级*/, Map<Integer/*班级*/, Long/*人数*/>> integerMap = list.stream().filter(t -> t.getScore() >= 60).collect(Collectors.groupingBy(t -> t.getGrade(), Collectors.groupingBy(t -> t.getClasses(), Collectors.counting())));
System.out.println("取出一年级一班及格人数:" + integerMap.get(1).get(1));

2-11):逗号拼接,去重 将每个ID以逗号方式拼接 & 对象重写 equals和hashCode

String dou = list.stream().distinct().map(mark -> mark.getId().toString()).filter(x -> !ObjectUtils.isEmpty(x)).collect(Collectors.joining(","));
System.out.println("逗号拼接,将每个ID以逗号方式拼接:={}"+dou);

2-12):limit  返回前几个元素信息 获取大于50前三位学生信息

Collections.sort(list, Comparator.comparing(TestStreamModel::getScore).reversed());// 倒序排列,删除 reversed()为正序
List<TestStreamModel> models = list.stream().filter(a -> a.getScore() > 50).limit(3).collect(Collectors.toList());
System.out.println("limit 获取大于50分的前三位学生:={}"+models);

2-13):skip  获取跳过几个元素后的信息 获取大于50前三位学生信息

Collections.sort(list, Comparator.comparing(TestStreamModel::getScore).reversed());// 倒序排列,删除 reversed()为正序
List<TestStreamModel> model = list.stream().filter(a -> a.getScore() > 50).skip(3).collect(Collectors.toList());
System.out.println("limit 获取大于50分的前三位学生:={}"+model);

=====================END========================

3-1):flatMap  

flatMap与map的区别在于* flatMap是将一个流中的每个值都转成一个个流,然后再将这些流扁平化成为一个流 。

举例说明,假设我们有一个字符串数组String[] strs = {"java8", "is", "easy", "to", "use"};

我们希望输出构成这一数组的所有非重复字符,那么我们可能首先会想到如下实现:

String[] strs = {"java8", "java8", "is", "easy", "to", "use"};
List<String[]> distinctStrs = Arrays.stream(strs)
        .map(str -> str.split(""))  // 映射成为Stream<String[]>
        .distinct()
        .collect(Collectors.toList());
System.out.println("映射处理flatMap:操作之后的数据为{}:");
distinctStrs.stream().forEach(ex -> {
    System.out.println(Arrays.stream(ex).collect(Collectors.joining(",")));
});

返回结果:
j,a,v,a,8
j,a,v,a,8
i,s
e,a,s,y
t,o
u,s,e

distinct只有对于一个包含多个字符的流进行操作才能达到我们的目的,即对Stream<String>进行操作。此时flatMap就可以达到我们的目的:

List<String> dis = Arrays.stream(strs)
                .map(str -> str.split(""))  // 映射成为Stream<String[]>
                .flatMap(Arrays::stream)  // 扁平化为Stream<String>
                .distinct()
                .collect(Collectors.toList());
System.out.println("映射处理flatMap:操作之后的数据为{}:");
dis.stream().forEach(s1 -> System.out.print(s1));

返回结果:jav8iseytou

4-1):allMatch : 查询所有学生成绩是否都大于 44 分

boolean isAdult = list.stream().allMatch(student -> student.getScore() >= 44);// 满足返回 true
System.out.println("查找 allMatch:" + isAdult);

4-2):anyMatch :查询所有学生是否有成绩是否都大于 44 分

boolean hasWhu = list.stream().anyMatch(student -> student.getScore() >= 98);// 满足返回 false
System.out.println("查找 anyMatch:" + hasWhu);

4-3):noneMatch :查询所有学生是否不存在大于98分的

boolean noneCs = list.stream().noneMatch(student -> student.getScore() >= 98); // 不存在返回 true ,否则 false
System.out.println("查找 noneMathch:" + noneCs);

4-4):findFirst : 查询满足条件排在第一位的学生信息

TestStreamModel findFirst = list.stream().filter(student -> student.getScore() >= 60).findFirst().orElse(new TestStreamModel());
System.out.println("查找 findFirst:" + findFirst);

4-5):findAny :  查询满足条件随机一个的学生信息 

TestStreamModel findAny = list.stream().filter(student -> student.getScore() >= 60).findAny().orElse(new TestStreamModel());
System.out.println("查找 findAny:" + findAny);

5-1): list 对象 根据时间排序

public class TestObject implements Serializable {

    private Date startTime;
    private Integer id;

    public TestObject(Date startTime, Integer id) {
        this.startTime = startTime;
        this.id = id;
    }

    public TestObject() {
    }

}

List<TestObject> objectList = new ArrayList<TestObject>() {{
    add(new TestObject(DateUtils.parseDate("2019-10-10 10:10:10", DateUtils.DEFAULT_TIME_FORMAT), 1));
    add(new TestObject(DateUtils.parseDate("2019-10-11 10:10:10", DateUtils.DEFAULT_TIME_FORMAT), 2));
    add(new TestObject(DateUtils.parseDate("2019-10-12 10:10:10", DateUtils.DEFAULT_TIME_FORMAT), 3));
    add(new TestObject(DateUtils.parseDate("2019-10-09 10:10:10", DateUtils.DEFAULT_TIME_FORMAT), 4));
    add(new TestObject(DateUtils.parseDate("2019-10-04 10:10:10", DateUtils.DEFAULT_TIME_FORMAT), 5));
    add(new TestObject(DateUtils.parseDate("2019-10-22 10:10:10", DateUtils.DEFAULT_TIME_FORMAT), 6));
}};
测试数据

倒序:

// 倒序
Collections.sort(objectList, new Comparator<TestObject>() {
    @Override
    public int compare(TestObject o1, TestObject o2) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date dt1 = o1.getStartTime();
            Date dt2 = o2.getStartTime();
            if (dt1.getTime() < dt2.getTime()) {
                return 1;
            } else if (dt1.getTime() > dt2.getTime()) {
                return -1;
            } else {
                return 0;
            }
        } catch (Exception e) {
            System.err.println("排列时间报错" + e.getMessage() + e);
        }
        return 0;

    }
});
System.out.println("倒序:={}"+ JSON.toJSONString(objectList));

正序:

 

// 正序
Collections.sort(objectList, new Comparator<TestObject>() {
    @Override
    public int compare(TestObject o1, TestObject o2) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            Date dt1 = o1.getStartTime();
            Date dt2 = o2.getStartTime();
            if (dt1.getTime() > dt2.getTime()) {
                return 1;
            } else if (dt1.getTime() < dt2.getTime()) {
                return -1;
            } else {
                return 0;
            }
        } catch (Exception e) {
            System.err.println("排列时间报错" + e.getMessage() + e);
        }
        return 0;

    }
});
System.out.println("正序:={}"+ JSON.toJSONString(objectList));

 

5-2): list 对象 根据时间排序【JDK8】

private void fanganer(List<CcBillPo> list) {
        //list 集合倒叙排序
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (list.size() > 1) {
            list.sort((a1, a2) -> {
                if (!ObjectUtils.isEmpty(a1.getCreateTime()) && !ObjectUtils.isEmpty(a2.getCreateTime())) {
                    try {
                        return df.parse(sdf.format(a2.getCreateTime())).compareTo(df.parse(sdf.format(a1.getCreateTime())));
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                }
                return 1;
            });
        }
    }

 

posted @ 2020-01-13 17:25  coding++  阅读(473)  评论(0编辑  收藏  举报