java学习笔记21--JDK1.8之后的新特性 Stream api

Stream API 从1.8引入的api, 都和集合有关。这些方法操作集合更方便:

例子:写一个方法找list集合中的所有偶数,并返回一个新的list集合;

代码如下:

public class Demo1 {
    public static void main(String[] args) {
//        写一个方法找list集合中的所有偶数,并返回一个新的list集合
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
        find(list);
        System.out.println(find(list));
    }
    private static List find(List<Integer> list) {
        List<Integer> list1 = new ArrayList<>();
        for (Integer integer : list) {
            if (integer % 2 == 0) {
                list1.add(integer);
            }
        }
        return list1;
    }
}

上面是求找偶数的方法,假设我们需要找奇数, 偶数乘2的数值等等要求,有一个新要求我们就要定义一个新方法,非常麻烦,所以引入了Stream api中的一些接口,操作方法,使用更方便。
以下是找偶数使用Stream api中的操作

public class StreamDemo {
    public static void main(String[] args) {
        List<Integer> list= Arrays.asList(1,2,3,4,5);
        //把集合变为流
        Stream<Integer> stream = list.stream();
        //调用流中的filter过滤方法,把奇数过滤掉,保留偶数
        Stream<Integer> integerStream = stream.filter(new Predicate<Integer>() {
            @Override
            public boolean test(Integer i) {
                return i % 2 == 0;
            }
        });
        //采用lambda表达式
        Stream<Integer> integerStream1 = stream.filter(i -> i % 2 == 0);
        //收集数据,Collector是一个收集器,toList()是转换为集合
        List<Integer> collect = integerStream.collect(Collectors.toList());
        System.out.println(collect);
    }
}

在Stream api 中,我们可以在匿名内部类处或者lambda表达式处更改操作求奇数,而不用再定义方法,其中Predicate是断言接口, filter是过滤方法,接下来将详细介绍几种常用的重要的接口,方法。注意在Stream中都要采用Collector收集器收集数据,才能打印出数据。

重要接口

1.Predicate 断言接口

对应 一个lambda表达式,一个参数,返回结果是boolean

2.Function 函数接口

对应的lambda 一个参数,一个返回结果,二者类型可以不一致

3.BiPridicate 双参数断言

对应的lambda 两个参数,返回结果是boolean

4.Consumer消费接口

    一个参数,没有结果

5.Biconsumer 双参数消费接口

    两个参数,没有结果

6.Supplier 生产接口

    没有参数,返回一个结果

Stream api

1.filter()

filter()进行过滤的,lambda返回为true就会留下,返回为false的就会过滤掉。
其需要的参数是Predicate 断言接口 ,多用于当需要返回结果为boolean类型时的操作,可以改变集合中元素的个数

2.map() 映射的

lambda把原有的元素转换为另一个元素,不会改变个数。其需要的参数是Function函数接口,即参数类型和返回结果可以不一致,故可以用来进行转变类型操作。比如可以把String类型通过map转变为数组类型。

3.flatMap() 扁平化映射

其需要的参数是Function函数接口,即参数类型和返回结果可以不一致,故可以用来进行转变类型操作。比如可以把String[]类型通过flatMap转变为流。
注:map()和flatMap()的区别:map()是10个元素的映射,结果得到的仍然是10个元素,flatMap()中是每个元素又转成小的流,内含多个子元素,所以10 个元素的flatMap的最终结果会多于10。

4.forEach()遍历流

接收一个Consumer

5.count()求个数

6.dintinct()去除重复

7.分组

Collectors中的groupingBy()方法是用来分组的,把分组规则传进去即可。最后面有此分组代码,可以参考,分别列举了不采用Stream分组的常规分组方法,采用Stream分组的方法;可以看出常规方法比较麻烦,Stream分组方法比较简单,尤其是当元素多的时候。

Stream api中重要的思想:

流水线思想 pipeline:把流中的数据一个接一个处理,每个数据会经过后续的filter,map等方法依次调用。
在整个执行过程中,lambda表达式是懒惰的,不执行终结方法的话,不会触发lambda的执行。
终结方法:collect ,sum,max,min…
运算过程中不会改变原始集合,收集器会生成新的集合对象。

例子

把最后终结方法的两行代码注释掉,输出语句没有一个执行:

public class Stream2 {
    public static void main(String[] args) {
        List<Integer> list= Arrays.asList(1,2,3,4,5);
        Stream<Integer> stream1 = list.stream();
        Stream<Integer> stream2=stream1.filter(i->{
            System.out.println("lambda表达式filter执行了");return i%2!=0;
        });//求奇数
        Stream<Integer> stream3 = stream2.map(i -> {
            System.out.println("lambda表达式map执行了");
            return i * 2;});//奇数再乘2
//        List<Integer> collect = stream3.collect(Collectors.toList());
//        System.out.println(collect);
    }
}

9.流的生 成:

1.用集合生成

list.stream();

2.用数字生成

IntStream.of()
代码:

public class IntStreamDemo {
    public static void main(String[] args) {
        //当流操作的是纯数字时,可以采用数字流
        //可以求和,最大最小值,平均值
        int sum = IntStream.of(1, 2, 3, 4, 5, 6,7).sum();
        System.out.println(sum);
        OptionalInt max = IntStream.of(1, 2, 3, 4, 5, 6, 7).max();
        System.out.println(max);
        OptionalInt min = IntStream.of(1, 2, 3, 4, 5, 6, 7).min();
        System.out.println(min);
        OptionalDouble average = IntStream.of(1, 2, 3, 4, 5, 6, 7).average();
        System.out.println(average);
    }
}

3.用数组生成

Arrays.stream(数组)// 把数组变成流
代码:

public class ArrayStream {
    public static void main(String[] args) {
        String[] s={"1","2","3","4","5"};
        Stream<String> stream = Arrays.stream(s);
        List<String> collect = stream.collect(Collectors.toList());
        System.out.println(collect);
    }
}

4.用文件生成

Files.lines()//把文件中的每一行读取出来作为元素。
代码:

public class FileStream {
    public static void main(String[] args) throws IOException {
        Stream<String> lines = Files.lines(Paths.get("heroes.txt"), Charset.forName("utf-8"));
       lines.forEach(string-> System.out.println(string));
    }
}

5.使用生产者接口

Stream.generate();用limit()限制生成的流的长度。其参数是supplier接口,无参数,返回一个结果;
代码:

public class GenerateStream {
    public static void main(String[] args) {
        Stream<Integer> limit = Stream.generate(() -> 5).limit(3);
        limit.forEach(i-> System.out.println(i));
        Random random = new Random();
        Stream.generate(()->random.nextInt(100)).limit(5).forEach(a-> System.out.println(a));
    }
}

10方法引用

实际上是对lambda表达式的扩展,就是可以把lambda表达式的形式转为方法引用的形式:

方法引用的格式:

1.对象::方法名

例如:System.out.println

Stream<Integer> limit = Stream.generate(() -> 5).limit(3);
//      limit.forEach(i-> System.out.println(i));//正常输出形式
        //类名::方法名
        limit.forEach(System.out::println);//方法引用形式

forEach方法里要的是Consumer接口,一个参数,没有返回结果,而System.out类中的println也是一个参数,没有返回值,所以可以把lambda表达式写成方法引用的形式。

2.类名::静态方法名

Class ABC{
public static Boolean aaa(Integer x){
//可以写好多代码
 Return x%2==0;
}
}

可以使用ABC::aaa代替其lambda表达式形式。

3.类名::new

可以取代Supplier接口的lambda
例如()->new Student()可以替换为:Student::new
建议:当有复杂逻辑时,lambda表达式的形式比较时,可以采用方法引用的第二种形式,把方法封装起来,调用时非常简单。
具体代码如下:

public class StreamYinYong {
    public static void main(String[] args) {
        Stream<Integer> limit = Stream.generate(() -> 5).limit(3);
    
        //第一种形式:类名::方法名
        //limit.forEach(i-> System.out.println(i));//正常输出形式
        limit.forEach(System.out::println);//方法引用形式

        List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);
        Stream<Integer> stream = integers.stream();
        //第二种: 类名::静态方法名
        List<Integer> collect = stream.filter(x -> x % 2 == 0).collect(Collectors.toList());//正常输出形式
        stream.filter(StreamYinYong::find).collect(Collectors.toList());

        //第三种:类名::new
        List<Student> collect1= Stream.generate(() -> new Student()).limit(2).collect(Collectors.toList());//正常输出形式
        Stream.generate(Student::new).limit(2).collect(Collectors.toList());

    }
    private static final boolean find(Integer x){
        return x%2==0;
    }
}

以下是以上方法和接口的代码实现

代码1:

filter(),map(), count(),distinct()方法的应用

public class Stream1 {
    public static void main(String[] args) {
        //采用Arrays工具类中asList方法把数组变为集合
        List<Integer> list= Arrays.asList(1,2,3,4,5);
        Stream<Integer> stream1 = list.stream();
        Stream<Integer> stream2=stream1.filter(i->i%2!=0);//求奇数
        Stream<Integer> stream3 = stream2.map(i -> i * 2);//奇数再乘2
        List<Integer> collect = stream3.collect(Collectors.toList());
        System.out.println(collect);
List<Integer> list1 = Arrays.asList(1, 2, 3, 1, 2);
        //计算个数
        long count = list1.stream().count();
        System.out.println(count);
        //去除重复元素
        Stream<Integer> distinct = list1.stream().distinct();
        List<Integer> collect1 = distinct.collect(Collectors.toList());
        System.out.println(collect1);
}

代码2:

flatMap(),forEach()方法的应用代码

public class TestFlatmap {
    public static void main(String[] args) {
        List<String[]>list= new ArrayList<>();
        list.add(new String[]{"大大","小小"});
        list.add(new String[]{"左左","右右"});
        list.add(new String[]{"前前","后后"});
        list.add(new String[]{"南南","北北"});
        Stream<String[]> stream = list.stream();
//        stream.flatMap(new Function<String[], Stream<?>>() {
//            @Override
//            public Stream<?> apply(String[] strings) {
//                return stream(strings);
//            }
//        });
        //采用lambda表达式
        //把数组变为流
        Stream<String> stringStream = stream.flatMap(strings -> stream(strings));
        //通过流把数组中的元素放在集合中
        List<String> collect = stringStream.collect(Collectors.toList());
        System.out.println(collect);

        //遍历流
        stringStream.forEach(s-> System.out.println(s));
    }
}

代码3:分组代码

public class StudentStream {
    public static void main(String[] args) {
        List<Student> list = new ArrayList<>();
        list.add(new Student("zhangsan", "男", "北京"));
        list.add(new Student("wangming", "女", "天津"));
        list.add(new Student("zhouzhou", "女", "北京"));
        list.add(new Student("lainglaing", "男", "西安"));
        list.add(new Student("lisi", "男", "北京"))
        //传统方法,按性别分组,map集合的键是性别,值是student 集合
        Map<String, List<Student>> map = new HashMap<>();
        for (Student s : list) {
            if (s.getSex().equals("男")) {
                List<Student> nan = map.get("男");//键找值
                map.put(s.getSex(), nan);
                if (nan == null) {
                    nan = new ArrayList<>();
                    map.put("男", nan);
                }
                nan.add(s);
            } else {
                List<Student> nv = map.get("女");
                map.put(s.getSex(), nv);
                if (nv == null) {
                    nv = new ArrayList<>();
                    map.put("女", nv);
                }
                nv.add(s);
            }
        }
        System.out.println(map);
        //采用流,按性别分组
        Stream<Student> stream = list.stream();
        Map<String, List<Student>> collect = stream.collect(Collectors.groupingBy(student -> student.getSex()));
        System.out.println(collect);
        //采用流,按地域分组
        Map<String, List<Student>> collect1 = list.stream().collect(Collectors.groupingBy(student -> student.getCity()));
        System.out.println(collect1);
    }
}

Stream 流的应用

有一个heroes.txt文件,里面存储了许多三国中的人物,有序号Id,姓名name,出生地loc,性别sex,出生日子birth,死亡日子death,武力值power。采用Stream从heroes.txt文件中读出数据,并把封装成一个Hero 类,在HeroTest类中实现以下要求:
// 1. 找到武将中武力前三的hero对象
// 2. 按出生地分组
// 3. 找出寿命前三的武将
// 4. 女性寿命最高的
// 5. 找出武力排名前三 100, 99, 97 97 ==> 4个人 吕布", “张飞”, “关羽”, "马超
// 6. 按各个年龄段分组: 0~20, 2140, 41~60, 60以上
// 7. 按武力段分组: >=90, 80~89, 70~79, <70
// 8. 按出生地分组后,统计各组人数

方法1:Stream 代码

public class HeroTest {
    public static void main(String[] args) throws IOException {
        //把文件转换为流
        Stream<String> lines = Files.lines(Paths.get("heroes.txt"), Charset.forName("utf-8"));
        //读取文件中的内容并存入到Hero类对象中
        Stream<String[]> stream = lines.map(string -> string.split("\t"));
        Stream<Hero> heroStream = stream.map(s -> new Hero(Integer.parseInt(s[0]), s[1], s[2], s[3], Integer.parseInt(s[4]),
                Integer.parseInt(s[5]), Integer.parseInt(s[6])));
        //把heroStream 流转为集合方便流的多次使用
        List<Hero> list = heroStream.collect(Collectors.toList());

        // 1. 找到武将中武力前三的hero对象, 提示流也可以排序
        Stream<Hero> limit = list.stream().sorted((h1, h2) -> {
            return -(h1.getPower() - h2.getPower());
        }).limit(3);
        List<Hero> collect = limit.collect(Collectors.toList());
        System.out.println(collect);

        // 2. 按出生地分组
        Map<String, List<Hero>> collect1 = list.stream().collect(Collectors.groupingBy(h -> h.getLoc()));
        System.out.println(collect1);

        // 3. 找出寿命前三的武将
        Stream<Hero> limit1 = list.stream().sorted((h1, h2) -> {
            return -((h1.getDeath() - h1.getBirth()) - (h2.getDeath() - h2.getBirth()));
        }).limit(3);
        List<Hero> collect2 = limit1.collect(Collectors.toList());
        System.out.println(collect2);

        // 4. 女性寿命最高的
        Stream<Hero> women = list.stream().filter(h -> h.getSex().equals("女")).sorted((h1, h2) -> {
            return -((h1.getDeath() - h1.getBirth()) - (h2.getDeath() - h2.getBirth()));
        }).limit(1);
        List<Hero> collect3 = women.collect(Collectors.toList());
        System.out.println(collect3);

        // 5. 找出武力排名前三(有武力相等的也算)  100, 99, 97 97 ==> 4个人 吕布", "张飞", "关羽", "马超
        Stream<Hero> sorted = list.stream().sorted((h1, h2) -> {
            return -(h1.getPower() - h2.getPower());
        }).limit(4);

        // 6. 按各个年龄段分组: 0~20, 21~40, 41~60, 60以上
        Map<String, List<Hero>> collect4 = list.stream().collect(Collectors.groupingBy(h -> {
            String s = null;
            int age = h.getDeath() - h.getBirth();
            if (age >= 0 && age <= 20) {
                s = "0~20";
            } else if (age >= 21 && age <= 40) {
                s = "21~40";
            } else if (age >= 41 && age <= 60) {
                s = "41~60";
            } else {
                s = "60以上";
            }
            return s;
        }));
        System.out.println(collect4);

        // 7. 按武力段分组: >=90, 80~89, 70~79, <70
        Map<String, List<Hero>> collect5 = list.stream().collect(Collectors.groupingBy(h -> {
            String s = null;
            int power = h.getPower();
            if (power < 70) {
                s = "<70";
            } else if (power >= 70 && power <= 79) {
                s = "70~79";
            } else if (power >= 80 && power <= 89) {
                s = "80~89";
            } else {
                s = ">=90";
            }
            return s;
        }));
        System.out.println(collect5);

        // 8. 按出生地分组后,统计各组人数
        Map<String, List<Hero>> collect6 = list.stream().collect(Collectors.groupingBy(h -> h.getLoc()));
        Set<String> keySet = collect6.keySet();
        for(String key:keySet){
            long count = collect6.get(key).stream().count();
            System.out.println("出生地:"+key+",出生的人数:"+count);
        }

    }
}

方法2:采用传统的流与集合

public class HeroTest1 {
    public static void main(String[] args) {
        //根据路径得到一个File对象
        try {
            FileInputStream in=new FileInputStream("heroes.txt");
            InputStreamReader isr=new InputStreamReader(in);
            BufferedReader br=new BufferedReader(isr);
            //把文件读出来换为Hero对象存入list集合中
            List<Hero>list=new ArrayList<>();
            String line=null;
            StringBuffer strings=new StringBuffer();
            while((line=br.readLine())!=null){
                String[] s= line.split("\t");
                Hero hero = new Hero(Integer.parseInt(s[0]), s[1], s[2], s[3], Integer.parseInt(s[4]),
                        Integer.parseInt(s[5]), Integer.parseInt(s[6]));
                list.add(hero);
            }
            System.out.println(list);


            // 1. 找到武将中武力前三的hero对象
            method1(list);

            // 2. 按出生地分组
            //说明,出生地太多了,找了几个代表性的,逻辑是对的
            method2(list);

            // 3. 找出寿命前三的武将
            method3(list);

            // 4. 女性寿命最高的
            method4(list);

            // 5. 找出武力排名前三  100, 99, 97 97 ==> 4个人 吕布", "张飞", "关羽", "马超
            method5(list);

            // 6. 按各个年龄段分组: 0~20, 2140, 41~60, 60以上
            method6(list);

            // 7. 按武力段分组: >=90, 80~89, 70~79, <70
            method7(list);

            // 8. 按出生地分组后,统计各组人数
            //说明,出生地太多了,找了几个代表性的
            method8(list);


        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    private static void method8(List<Hero> list) {
        Map<String,List<Hero>> map1=new HashMap<>();
        List<Hero> heroList1;
        for(Hero h:list) {
            if (h.getLoc().equals("云南")) {
                heroList1 = map1.get(h.getLoc());
                //第一次没有这个分组存在时需要创建一个集合存储分组元素
                if (heroList1 == null) {
                    heroList1 = new ArrayList<>();
                    map1.put(h.getLoc(), heroList1);//Map集合中加入键,值
                }
                heroList1.add(h);//Map集合中的值list集合中添加元素
            } else if (h.getLoc().equals("江陵")) {
                heroList1 = map1.get(h.getLoc());
                //第一次没有这个分组存在时需要创建一个集合存储分组元素
                if (heroList1 == null) {
                    heroList1 = new ArrayList<>();
                    map1.put(h.getLoc(), heroList1);//Map集合中加入键,值
                }
                heroList1.add(h);//Map集合中的值list集合中添加元素
            }
        }
        // System.out.println(map1);
        //统计人数
        Set<String> keySet = map1.keySet();
        for(String key:keySet){
            System.out.println(key+"人数为:"+map1.get(key).size());
        }

    }

    private static void method7(List<Hero> list) {
        Map<String,List<Hero>> map=new HashMap<>();
        for(Hero h:list){
            String string = null;
            int power = h.getPower() - h.getPower();
            if (power >=90) {
                string = ">=90";
                List<Hero> heroList1 = map.get(string);
                //第一次没有这个分组存在时需要创建一个集合存储分组元素
                if (heroList1 == null) {
                    heroList1= new ArrayList<>();
                    map.put(string, heroList1);//Map集合中加入键,值
                }
                heroList1.add(h);//Map集合中的值list集合中添加元素
            } else if (power >= 80 && power <= 89) {
                string= "21~40";
                List<Hero> heroList1 = map.get(string);
                //第一次没有这个分组存在时需要创建一个集合存储分组元素
                if (heroList1 == null) {
                    heroList1= new ArrayList<>();
                    map.put(string, heroList1);//Map集合中加入键,值
                }
                heroList1.add(h);//Map集合中的值list集合中添加元素
            } else if (power >= 70 && power <= 79) {
                string = "41~60";
                List<Hero> heroList1 = map.get(string);
                //第一次没有这个分组存在时需要创建一个集合存储分组元素
                if (heroList1 == null) {
                    heroList1= new ArrayList<>();
                    map.put(string, heroList1);//Map集合中加入键,值
                }
                heroList1.add(h);//Map集合中的值list集合中添加元素
            } else {
                string = "<70";
                List<Hero> heroList1 = map.get(string);
                //第一次没有这个分组存在时需要创建一个集合存储分组元素
                if (heroList1 == null) {
                    heroList1= new ArrayList<>();
                    map.put(string, heroList1);//Map集合中加入键,值
                }
                heroList1.add(h);//Map集合中的值list集合中添加元素
            }
        }
        System.out.println(map);

    }

    private static void method6(List<Hero> list) {
        Map<String,List<Hero>> map=new HashMap<>();
        for(Hero h:list){
            String string = null;
            int age = h.getDeath() - h.getBirth();
            if (age >= 0 && age <= 20) {
                string = "0~20";
                List<Hero> heroList1 = map.get(string);
                //第一次没有这个分组存在时需要创建一个集合存储分组元素
                if (heroList1 == null) {
                    heroList1= new ArrayList<>();
                    map.put(string, heroList1);//Map集合中加入键,值
                }
                heroList1.add(h);//Map集合中的值list集合中添加元素
            } else if (age >= 21 && age <= 40) {
                string= "21~40";
                List<Hero> heroList1 = map.get(string);
                //第一次没有这个分组存在时需要创建一个集合存储分组元素
                if (heroList1 == null) {
                    heroList1= new ArrayList<>();
                    map.put(string, heroList1);//Map集合中加入键,值
                }
                heroList1.add(h);//Map集合中的值list集合中添加元素
            } else if (age >= 41 && age <= 60) {
                string = "41~60";
                List<Hero> heroList1 = map.get(string);
                //第一次没有这个分组存在时需要创建一个集合存储分组元素
                if (heroList1 == null) {
                    heroList1= new ArrayList<>();
                    map.put(string, heroList1);//Map集合中加入键,值
                }
                heroList1.add(h);//Map集合中的值list集合中添加元素
            } else {
                string = "60以上";
                List<Hero> heroList1 = map.get(string);
                //第一次没有这个分组存在时需要创建一个集合存储分组元素
                if (heroList1 == null) {
                    heroList1= new ArrayList<>();
                    map.put(string, heroList1);//Map集合中加入键,值
                }
                heroList1.add(h);//Map集合中的值list集合中添加元素
            }
        }
        System.out.println(map);
    }

    private static void method5(List<Hero> list) {
        TreeSet<Hero> treeSet=new TreeSet<>((o1, o2) -> {
            int p= -(o1.getPower()-o2.getPower());
            int p2=p==0?o1.getId()-o2.getId():p;//有武力值一样的,需要用id来区分不是同一个对象
            return p2;
        });
        for(Hero h:list){
            treeSet.add(h);
        }
        //System.out.println(treeSet);
        //武力前三的hero对象存入list集合
        List<Hero> list2 = new ArrayList<>();
        int i=0;
        for(Hero h:treeSet){
            if(i<4){
                list2.add(h);
            }
            i++;
        }
        System.out.println(list2);

    }

    private static void method4(List<Hero> list) {
        TreeSet<Hero> treeSet=new TreeSet<>((o1, o2) -> {
            int p= -((o1.getDeath()-o1.getBirth())-(o2.getDeath()-o2.getBirth()));
            int p2=p==0?o1.getId()-o2.getId():p;//有寿命一样的,需要用id来区分不是同一个对象
            return p2;
        });
        for(Hero h:list){
            if(h.getSex().equals("女"))
                treeSet.add(h);
        }
        //System.out.println(treeSet);
        //寿命最高的女性对象存入list集合
        List<Hero> list2 = new ArrayList<>();
        int i=0;
        for(Hero h:treeSet){
            if(i<1){
                list2.add(h);
            }
            i++;
        }
        System.out.println(list2);
    }



    private static void method3(List<Hero> list) {
        TreeSet<Hero> treeSet=new TreeSet<>((o1, o2) -> {
            int p= -((o1.getDeath()-o1.getBirth())-(o2.getDeath()-o2.getBirth()));
            int p2=p==0?o1.getId()-o2.getId():p;//有寿命一样的,需要用id来区分不是同一个对象
            return p2;
        });
        for(Hero h:list){
            treeSet.add(h);
        }
        //System.out.println(treeSet);
        //寿命前三的hero对象存入list集合
        List<Hero> list2 = new ArrayList<>();
        int i=0;
        for(Hero h:treeSet){
            if(i<3){
                list2.add(h);
            }
            i++;
        }
        System.out.println(list2);
    }


    private static void method2(List<Hero> list) {
        //定义map 集合存储分组元素
        Map<String,List<Hero>> map=new HashMap<>();
        List<Hero> heroList;
        for(Hero h:list) {
            if (h.getLoc().equals("")) {
                heroList = map.get(h.getLoc());
                //第一次没有这个分组存在时需要创建一个集合存储分组元素
                if (heroList == null) {
                    heroList = new ArrayList<>();
                    map.put(h.getLoc(), heroList);//Map集合中加入键,值
                }
                heroList.add(h);//Map集合中的值list集合中添加元素
            } else if (h.getLoc().equals("武陵")) {
                heroList = map.get(h.getLoc());
                //第一次没有这个分组存在时需要创建一个集合存储分组元素
                if (heroList == null) {
                    heroList = new ArrayList<>();
                    map.put(h.getLoc(), heroList);//Map集合中加入键,值
                }
                heroList.add(h);//Map集合中的值list集合中添加元素
            }
        }
        System.out.println(map);
    }

    private static void method1(List<Hero> list) {
        TreeSet<Hero> treeSet=new TreeSet<>((o1, o2) -> {
            int p= -(o1.getPower()-o2.getPower());
            int p2=p==0?o1.getId()-o2.getId():p;//有武力值一样的,需要用id来区分不是同一个对象
            return p2;
        });
        for(Hero h:list){
            treeSet.add(h);
        }
        //System.out.println(treeSet);
        //武力前三的hero对象存入list集合
        List<Hero> list2 = new ArrayList<>();
        int i=0;
        for(Hero h:treeSet){
            if(i<3){
                list2.add(h);
            }
            i++;
        }
        System.out.println(list2);
    }
}

Hero类

public class Hero {
    private int id;
    private String name;
    private String loc; // location
    private String sex;
    private int birth;
    private int death;
    private int power;
    public Hero(int id,String name,String loc,String sex,int birth,int death,int power){
        this.id=id;
        this.name=name;
        this.loc=loc;
        this.birth=birth;
        this.death=death;
        this.power=power;
        this.sex=sex;
    }

    @Override
    public String toString() {
        return "Hero{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", loc='" + loc + '\'' +
                ", sex='" + sex + '\'' +
                ", birth=" + birth +
                ", death=" + death +
                ", power=" + power +
                '}';
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getLoc() {
        return loc;
    }

    public void setLoc(String loc) {
        this.loc = loc;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getBirth() {
        return birth;
    }

    public void setBirth(int birth) {
        this.birth = birth;
    }

    public int getDeath() {
        return death;
    }

    public void setDeath(int death) {
        this.death = death;
    }

    public int getPower() {
        return power;
    }

    public void setPower(int power) {
        this.power = power;
    }
}

版权声明:本文为qq_41804322原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。