java基础总结(107)--排序

目录

目录

0公共的知识

list与数组相互转化

map转list

list转map

2对数组进行排序

 

3list排序

  3.1基础类型List排序

  3.2对象List单属性排序

  3.3对象List多属性排序

4map排序



0公共的知识

list与数组相互转化

1 数组转换为List
1.1 使用java.util.Arrays工具类中的asList()方法

String[] arrays = {"a", "b", "c"};
List<String> list = Arrays.asList(arrays);

注意 : 将数组转换List后,不能对List增删,只能查改,否则抛出 UnsupportedOperationException异常

对转换后的List插入一条数据

list.add("d");

执行后抛出 :

java.lang.UnsupportedOperationException
    at java.util.AbstractList.add(AbstractList.java:148)
    at java.util.AbstractList.add(AbstractList.java:108)

原因解析:

Arrays.asList(strArray)返回值是java.util.Arrays类中一个私有静态内部类java.util.Arrays.ArrayList,它并非java.util.ArrayList类。java.util.Arrays.ArrayList类具有 set(),get(),contains()等方法,但是不具有添加add()或删除remove()方法,所以调用add()方法会报错。

使用场景:Arrays.asList(strArray)方式仅能用在将数组转换为List后,不需要增删其中的值,仅作为数据源读取使用。

1.2 使用Stream中的Collector收集器

String[] arrays = {"a", "b", "c"};
List<String> listStrings = Stream.of(arrays).collect(Collectors.toList());

转换后的List 属于 java.util.ArrayList 能进行正常的增删查操作
2. List转换为数组
2.1 使用Stream

List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        String[] strings = list.stream().toArray(String[]::new);

2.2 使用List中的toArray()方法

List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
String[] strings = list.toArray(new String[list.size()]);        

————————————————
版权声明:本文为CSDN博主「makesailing」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_37653556/article/details/83271784

map转list

            Map<String, String> map = new HashMap<String, String>();
            map.put("1", "AA");
            map.put("2", "BB");
            map.put("3", "CC");
            map.put("4", "DD");
         
            Collection<String> valueCollection = map.values();  //获取map所有的value
            final int size = valueCollection.size();
        
            List<String> valueList = new ArrayList<String>(valueCollection);  //转换成list
————————————————
版权声明:本文为CSDN博主「狂奔的黑驴」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/yuzhoaheyou/article/details/88952249

list转map

List集合转Map,用到的是Stream中Collectors的toMap方法:Collectors.toMap
具体用法实例如下:

//声明一个List集合
List<Person> list = new ArrayList();  
        list.add(new Person("1001", "小A"));  
        list.add(new Person("1002", "小B"));  
        list.add(new Person("1003", "小C"));
        System.out.println(list);
//将list转换map
Map<String, String> map = list.stream().collect(Collectors.toMap(Person::getId, Person::getName));
        System.out.println(map);


输出结果为:

注意:用Collectors的toMap方法转换List,一般会遇到两个问题。一个是转换map,key重复问题;另一个是空指针异常,即转为map的value是null。
问题解决!!!
一、第一种问题报的错误如下:Duplicate key

原因是声明List集合时,有的值重复,如图:

解决方法:(分三种,具体哪种看业务需求)
1.重复时用后面的value 覆盖前面的value

Map<String, String> map = list.stream().collect(Collectors.toMap(Person::getId, Person::getName,(key1 , key2)-> key2 ));
        System.out.println(map); 

输出结果:

2.重复时将前面的value 和后面的value拼接起来;

Map<String, String> map = list.stream().collect(Collectors.toMap(Person::getId, Person::getName,(key1 , key2)-> key1+","+key2 ));
        System.out.println(map);

输出结果:

3.重复时将重复key的数据组成集合

Map<String, List<String>> map = list.stream().collect(Collectors.toMap(Person::getId,
                p ->  {
                     List<String> getNameList = new ArrayList<>();
                         getNameList.add(p.getName());
                         return getNameList;
                     },
                     (List<String> value1, List<String> value2) -> {
                         value1.addAll(value2);
                         return value1;
                     }
                 ));
       
         System.out.println(map);


输出结果:

二、第二种问题报的错误如下:NullPointerException

原因是声明List集合时有的值为空(如图),但是HashMap中k,v是可以存null值的。

解决方法:在转换流中加上判空,即便value为空,依旧输出。(与上面方法三相同)

Map<String, List<String>> map = list.stream().collect(Collectors.toMap(Person::getId,
                p ->  {
                     List<String> getNameList = new ArrayList<>();
                         getNameList.add(p.getName());
                         return getNameList;
                     },
                     (List<String> value1, List<String> value2) -> {
                         value1.addAll(value2);
                         return value1;
                     }
                 ))
         System.out.println(map);


输出结果为:

————————————————
版权声明:本文为CSDN博主「菜鸟驿站ㅤ」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_39629277/article/details/83012548

 

2对数组进行排序

来自:https://blog.csdn.net/weixin_41987908/article/details/90445062

 其实Arrays.Sort(str) 是不稳定的,稳定排序可以用Arrays.parallelSort(str)
       若是升序直接Arrays.Sort(str)  就可以,若不是则得改造一下
        Integer[]str={1,3,4,5,7,2};
        Arrays.sort(str,new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                //反序有 -   若是正序则去掉 -
                return -o1.compareTo(o2);
            }
        });
        System.out.println(Arrays.toString(str));

java8 数组排序:

目前我只会先变为list 在转数组不会一次性转数组(还得继续学习)
    反序:
        Integer[]str={1,3,4,5,7,2};
        List<Integer> collect = Arrays.stream(str).sorted(Comparator.reverseOrder()).collect(Collectors.toList());
        Integer[] integers = collect.toArray(new Integer[6]);
        String s = Arrays.toString(integers);
        System.out.println(s);
        输出:[7, 5, 4, 3, 2, 1]  
    正序:
   Comparator.reverseOrder()   改为 Comparator.naturalOrder()    就行

如果是一个对象的一个属性排序则:

            List<FollowIMSI> collect = listResult.stream()
            .sorted(Comparator.comparing(FollowIMSI::getFollowDegree).reversed())
            .collect(Collectors.toList());

如果两个对象的一个属性排序:

List<Human> humans = new ArrayList<>();
humans.add(new Human("Sarah", 10));
humans.add(new Human("Jack", 12));
正序是:
Collections.sort(humans, Comparator.comparing(Human::getName));
反序是:
Collections.sort(humans, Comparator.comparing(Human::getName).reversed());

多条件排序:

//先按年龄从小到大排序,年龄相同再按id从小到大排序
personList.stream().sorted(Comparator.comparing((Person::getAge).thenComparing(Person::getId())).collect(Collectors.toList()) 

 

 

 

 

 

3list排序

  3.1基础类型List排序

  来自https://my.oschina.net/sdlvzg/blog/2243766

//对数字进行排序
List<Integer> nums = Arrays.asList(3,1,5,2,9,8,4,10,6,7);
nums.sort(Comparator.reverseOrder()); //reverseOrder倒序
System.err.println("倒序:"+nums);

nums.sort(Comparator.naturalOrder()); //naturalOrder自然排序即:正序
System.err.println("正序:"+nums);

  3.2对象List单属性排序

List<Developer> listDevs = ComparatorTest.getDevelopers();

System.out.println("排序前:");
//JAVA8的写法,循环
listDevs.forEach((developer)->System.out.println(developer));

//第一个写法
Collections.sort(listDevs, new Comparator<Developer>() {
    @Override
    public int compare(Developer o1, Developer o2) {
        return o1.getAge().compareTo(o2.getAge());
    }
});
//第二个写法,JAVA8的写法,List 接口支持直接使用 sort 该方法,不再需要使用 Collections.sort 了
//listDevs.sort(listDevs, new Comparator<Developer>() {
//   @Override
//   public int compare(Developer o1, Developer o2) {
//       return o1.getAge().compareTo(o2.getAge();
//   }
//});

//第三个写法,Lambda写法,JAVA8的写法
//listDevs.sort((Developer o1, Developer o2)->o1.getAge().compareTo(o2.getAge()));

//第四个写法,Lambda写法,JAVA8的写法
//listDevs.sort((o1, o2)->o1.getAge().compareTo(o2.getAge()));

//第五写法,个Lambda写法,JAVA8的写法
//listDevs.sort(Comparator.comparing(Developer::getAge));

//第六写法,个Lambda写法,JAVA8的写法
Comparator<Developer> ageComparator = (o1, o2)->o1.getAge().compareTo(o2.getAge());
listDevs.sort(ageComparator);       //按上面配置的顺序取值
listDevs.sort(ageComparator.reversed());    //按上面配置的顺序反向取值

System.out.println("排序后:");
//JAVA8的写法,循环
listDevs.forEach((developer)->System.out.println(developer));

  3.3对象List多属性排序

//        多条件排序第一个写法,先按Age排序,再根据Salary排序
//        Comparator<Developer> comparator = (o1, o2) -> {
//            if (o1.getName().equals(o2.getName())) {
//                return o1.getSalary().compareTo(o2.getSalary());
//            }
//            return o2.getAge().compareTo(o1.getAge());
//        };
//        listDevs.sort(comparator.reversed());

//        多条件排序,先按Age排序,再根据Salary排序
//        Comparator<Developer> ageComparator = (o1, o2)->o1.getAge().compareTo(o2.getAge());
//        Comparator<Developer> salaryComparator = (o1, o2)->o1.getSalary().compareTo(o2.getSalary());
//        listDevs.sort(ageComparator.thenComparing(salaryComparator));

//        多条件排序第二个写法,先按Age排序,再根据Salary排序
listDevs.sort(Comparator.comparing(Developer::getAge).thenComparing(Developer::getSalary));

 

 

来自https://blog.csdn.net/qq_23179075/article/details/78753136

在日常开发中,很多时候都需要对一些数据进行排序的操作。然而那些数据一般都是放在一个集合中如:Map ,Set ,List 等集合中。他们都提共了一个排序方法 sort(),要对数据排序直接使用这个方法就行,但是要保证集合中的对象是 可比较的。

怎么让一个对象是 可比较的,那就需要该对象实现 Comparable<T> 接口啦。然后重写里面的
compareTo()方法。我们可以看到Java中很多类都是实现类这个接口的 如:Integer,Long 等等。。。

假设我们有一个学生类,默认需要按学生的年龄字段 age 进行排序 代码如下:

public class Student implements Comparable<Student> {
    private int id;
    private int age;
    private String name;

    public Student(int id, int age, String name) {
        this.id = id;
        this.age = age;
        this.name = name;
    }
    @Override
    public int compareTo(Student o) {
        //降序
        //return o.age - this.age;
        //升序
        return this.age - o.age;        
    }
    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

这里说一下重写的 public int compareTo(Student o){} 这个方法,它返回三种 int 类型的值: 负整数,零 ,正整数。

返回值含义
负整数当前对象的值 < 比较对象的值 , 位置排在前
当前对象的值 = 比较对象的值 , 位置不变
正整数当前对象的值 > 比较对象的值 , 位置排在后

 测试代码

public static void main(String args[]){
        List<Student> list = new ArrayList<>();
        list.add(new Student(1,25,"关羽"));
        list.add(new Student(2,21,"张飞"));
        list.add(new Student(3,18,"刘备"));
        list.add(new Student(4,32,"袁绍"));
        list.add(new Student(5,36,"赵云"));
        list.add(new Student(6,16,"曹操"));
        System.out.println("排序前:");
        for (Student student : list) {
            System.out.println(student.toString());
        }
        //使用默认排序
        Collections.sort(list);
        System.out.println("默认排序后:");
        for (Student student : list) {
            System.out.println(student.toString());
        }
}

输出日志:

排序前:
Student{id=1, age=25, name='关羽'}
Student{id=2, age=21, name='张飞'}
Student{id=3, age=18, name='刘备'}
Student{id=4, age=32, name='袁绍'}
Student{id=5, age=36, name='赵云'}
Student{id=6, age=16, name='曹操'}
默认排序后:
Student{id=6, age=16, name='曹操'}
Student{id=3, age=18, name='刘备'}
Student{id=2, age=21, name='张飞'}
Student{id=1, age=25, name='关羽'}
Student{id=4, age=32, name='袁绍'}
Student{id=5, age=36, name='赵云'}

比较器的使用
这个时候需求又来了,默认是用 age 排序,但是有的时候需要用 id 来排序怎么办? 这个时候比较器 :Comparator 就排上用场了。

Comparator 的使用有两种方式:

Collections.sort(list,Comparator<T>);
list.sort(Comparator<T>);
其实主要是看 Comparator 接口的实现,重写里面的 compare 方法。代码如下:
 

//自定义排序1
Collections.sort(list, new Comparator<Student>() {
    @Override
    public int compare(Student o1, Student o2) {
        return o1.getId() - o2.getId();
    }
});

compare(Student o1, Student o2) 方法的返回值跟 Comparable<> 接口中的 compareTo(Student o) 方法 返回值意思相同。另一种写法如下: 

//自定义排序2
list.sort(new Comparator<Student>() {
    @Override
    public int compare(Student o1, Student o2) {
        return o1.getId() - o2.getId();
    }
});

 输出日志:

排序前:
Student{id=1, age=25, name='关羽'}
Student{id=2, age=21, name='张飞'}
Student{id=3, age=18, name='刘备'}
Student{id=4, age=32, name='袁绍'}
Student{id=5, age=36, name='赵云'}
Student{id=6, age=16, name='曹操'}
自定义排序后:
Student{id=1, age=25, name='关羽'}
Student{id=2, age=21, name='张飞'}
Student{id=3, age=18, name='刘备'}
Student{id=4, age=32, name='袁绍'}
Student{id=5, age=36, name='赵云'}
Student{id=6, age=16, name='曹操'}

4map排序

如果是treemap对象,本来就具备排序功能。所以不需要单独的排序

       TreeMap<String, Integer> treeMap = new TreeMap<>();
        treeMap.put("k", 1);
        treeMap.put("w", 3);
        treeMap.put("z", 2);
        System.out.println(treeMap);

执行输出:

{k=1, w=3, z=2}

TreeMap默认是按照key的自然顺序升序排列的,比如上面k, w, z,按照它们的ASCII码值排序就是kwz。下面博客介绍了如何修改treemap的排序规则。

来自https://www.cnblogs.com/huiyi0521/p/10990543.html

TreeMap默认是升序的,如果我们需要改变排序方式,则需要使用比较器:Comparator。

Comparator可以对集合对象或者数组进行排序的比较器接口,实现该接口的public compare(T o1,To2)方法即可实现排序,该方法主要是根据第一个参数o1,小于、等于或者大于o2分别返回负整数、0或者正整数。代码如下:

public class TreeMapTest {
    public static void main(String[] args) {
        Map<String, String> map = new TreeMap<String, String>(
                new Comparator<String>() {
                    public int compare(String obj1, String obj2) {
                        // 降序排序
                        return obj2.compareTo(obj1);
                    }
                });
        map.put("c", "ccccc");
        map.put("a", "aaaaa");
        map.put("b", "bbbbb");
        map.put("d", "ddddd");

        Set<String> keySet = map.keySet();
        Iterator<String> iter = keySet.iterator();
        while (iter.hasNext()) {
            String key = iter.next();
            System.out.println(key + ":" + map.get(key));
        }
    }
}
运行结果如下:
d:ddddd
c:ccccc
b:bbbbb
a:aaaaa

上面例子是对根据TreeMap的key值来进行排序的,但是有时我们需要根据TreeMap的value来进行排序。对value排序我们就需要 借助于Collections的sort(List<T> list, Comparator<? super T> c)方法,该方法根据指定比较器产生的顺序对指定列表进行排序。但是有一个前提条件,那就是所有的元素都必须能够根据所提供的比较器来进行比较。如下:

public class TreeMapTest {
    public static void main(String[] args) {
        Map<String, String> map = new TreeMap<String, String>();
        map.put("d", "ddddd");
        map.put("b", "bbbbb");
        map.put("a", "aaaaa");
        map.put("c", "ccccc");

        //这里将map.entrySet()转换成list
        List<Map.Entry<String,String>> list = new ArrayList<Map.Entry<String,String>>(map.entrySet());
        //然后通过比较器来实现排序
        Collections.sort(list,new Comparator<Map.Entry<String,String>>() {
            //升序排序
            public int compare(Entry<String, String> o1,
                    Entry<String, String> o2) {
                return o1.getValue().compareTo(o2.getValue());
            }
        });
        for(Map.Entry<String,String> mapping:list){                System.out.println(mapping.getKey()+":"+mapping.getValue()); 
          } 
    }
}
运行结果如下:
d:ddddd
c:ccccc
b:bbbbb
a:aaaaa

我们都是HashMap的值是没有顺序的,他是按照key的HashCode来实现的。对于这个无序的HashMap我们要怎么来实现排序呢?参照TreeMap的value排序,我们一样的也可以实现HashMap的排序。

public class HashMapTest {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<String, String>();
        map.put("c", "ccccc");
        map.put("a", "aaaaa");
        map.put("b", "bbbbb");
        map.put("d", "ddddd");

        List<Map.Entry<String,String>> list = new ArrayList<Map.Entry<String,String>>(map.entrySet());
        Collections.sort(list,new Comparator<Map.Entry<String,String>>() {
            //升序排序
            public int compare(Entry<String, String> o1,
                    Entry<String, String> o2) {
                return o1.getValue().compareTo(o2.getValue());
            }

        });

        for(Map.Entry<String,String> mapping:list){ 
               System.out.println(mapping.getKey()+":"+mapping.getValue()); 
          } 
     }
}

运行结果如下:
d:ddddd
c:ccccc
b:bbbbb
a:aaaaa

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值