栏目分类:
子分类:
返回
终身学习网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
终身学习网 > IT > 软件开发 > 后端开发 > Java

javaSE数组排序 java.util.Arrays.sort()

Java 更新时间:发布时间: 百科书网 趣学号
import java.util.Arrays;
import java.util.Comparator;
import java.util.Random;

public class TestArrSort {

    public static void main(String[] aa) {
//        sort1();
//        sort2();
//        sort3();
        myTestArraysSort();
    }


    public static void sort1() {
        Integer[] nums = new Integer[10];
        //数组下标范围是0-9
        //随机数
        Random random = new Random();
        for (int i = 0; i < 10; i++) {
            //注意这里nums[i]是整数integer对象,不是整型int
            nums[i] = random.nextInt(1, 101);
        }
        //有必要系统研究一下Arrays类,当然前提是会用,
        
        System.out.println("排序前:" + Arrays.toString(nums));

        //升序排序,参数是Object类,使用了多态
        Arrays.sort(nums);
        //排序后结果输出
        System.out.println("升序排序后:" + Arrays.toString(nums));

        //降序排序
        //创建了一个接口,这个接口应该有一个方法比较compare
        //这就是规范
        //然后我们覆盖方法之后就能排序了 。
        //当然,是不是很疑惑,前面也排序了,但是没有new接口(其实接口也是不能new的,我们new的应该是一个具体实现类,具体我还需要学习。)
        //答案就是:前面的排序是人家默认就有的接口,这里是我们写方法覆盖前面方法
        //不要忘了最终目的,实现降序排序
        Arrays.sort(nums, new Comparator() {
            @Override
            public int compare(Integer obj1, Integer obj2) {

                //前者减后者
                // 注意obj1还是对象,不是整型值,这里绝对不是 5-1 那么简单
                //如果是这样,那么是升序,也就是没有覆盖的方法
//              return obj1-obj2;
                //后者减前者--最终实现降序排序
                return obj2 - obj1;
            }
        });
        System.out.println("降序排序后:" + Arrays.toString(nums));
        //idea又给我提示了说有更简单的方法,于是我就用了一下,毕竟应该是更简单的方法思想更好。
        //最终就是这样, 我的jdk版本是17,这里是jdk8的最重要的新特性Lambda 表达式
        //具体我也不会,暂时没有学
        //我研究了一下,找到了等价关系,我想升序,所以把用前者减后者了,
        
        Arrays.sort(nums, (obj1, obj2) -> obj1 - obj2);

        //测试--
        System.out.println("升序排序后:" + Arrays.toString(nums));

        //先给它降序一下
        Arrays.sort(nums, (obj1, obj2) -> obj2 - obj1);
        //我把降序改为升序,然后idea又提示我有新的方法,我又点了一下
        //于是就变成了这样,这点我就没有办法修改了--其实可以继承然后覆盖方法,似乎又回到了降序最初的方法。给我在这里整死循环呢
        //所以这个目前来说只能升序
        //为了测试我在上面补充了降序
        Arrays.sort(nums, Comparator.comparingInt(num -> num));

        //测试--
        System.out.println("升序排序后:" + Arrays.toString(nums));

        


        

        //我首先写一个...我看过老师的一个例子,稍微修改了一下
        //仅供参考,
        for (int i = 0; i < nums.length / 2; i++) {
            //i是待交换的下标,
            //随机下标范围:[length/2+1,length)
            int j = random.nextInt(nums.length / 2 + 1, nums.length);
            //两两交换num[i]和[end]
            //新建地址temp
            Integer temp = nums[i];
            //上面是地址拷贝,下面也是
            nums[i] = nums[j];
            nums[j] = temp;
        }
        System.out.println("乱序排序后:" + Arrays.toString(nums));
        //不扯了,继续按照规范,新建接口,然后写覆盖方法实现乱序
        Arrays.sort(nums, new Comparator() {
            @Override
            public int compare(Integer obj1, Integer obj2) {

                //前者减后者
                // 注意num1还是对象,不是整型值,这里绝对不是 5-1 那么简单
                //如果是这样,那么是升序,也就是没有覆盖的方法
//              return obj1-obj2;
                //后者减前者--最终实现降序排序
//                return obj2-obj1;
                //乱序
                return Math.random() < 0.5 ? 1 : -1;
            }
        });
//        Arrays.sort(nums, (obj1, obj2) -> Math.random()<0.5?1:-1);  //这样写也可以
        System.out.println("乱序排序后:" + Arrays.toString(nums));
    }

    //sort1是Integer类的排序,然后就是String类的排序
    public static void sort2() {
        //问题一:String类怎么排序
        //按照首字母的ASCII码(值)大小,字符串长度,如果字符串是汉字,汉字首字母的笔画(感觉String已经不能表示汉字类了)...
        var lang = new String[]{"java", "C", "C++", "B", "go", "python", "javascript", "A"};

        //排序前
        System.out.println(Arrays.toString(lang));
        //按照ASCII码大小升序排序
        Arrays.sort(lang);
        System.out.println("按首字符的ASCII升序:" + Arrays.toString(lang));

        //降序
        //这是一个新的方法
        Arrays.sort(lang, Comparator.reverseOrder());
        //也可以自己写
//        Arrays.sort(lang, (obj1,obj2)->obj2.charAt(0)-obj1.charAt(0));

        System.out.println("按首字符的ASCII降序:" + Arrays.toString(lang));
        //乱序
        Arrays.sort(lang, (obj1, obj2) -> Math.random() > .5 ? 1 : -1);
        System.out.println("按首字符的ASCII降序:" + Arrays.toString(lang));


        //按字符个数/字符串长度排序
        //有点类似Integer; 同样强调obj1,obj2是String类型
        Arrays.sort(lang, (obj1, obj2) -> obj1.length() - obj2.length());
        //下面是idea给我提示的另一种写法
//        Arrays.sort(lang, Comparator.comparingInt(String::length));
        System.out.println(Arrays.toString(lang));

        //降序
        //这是一个新的方法
        Arrays.sort(lang, (obj1, obj2) -> obj2.length() - obj1.length());
        System.out.println(Arrays.toString(lang));
        //乱序:这个不受排序方式影响,和前面一样
        Arrays.sort(lang, (obj1, obj2) -> Math.random() > .5 ? 1 : -1);
        System.out.println(Arrays.toString(lang));

    }

    //最后自定义类排序
    public static void sort3() {
        //定义users数组
        User[] users = new User[6];
        //赋值
        users[0] = new User(1, "秦始皇", "123456");
        users[1] = new User(2, "汉武帝", "123456");
        users[2] = new User(3, "唐太宗", "123456");
        users[3] = new User(4, "宋太祖", "123456");
        users[4] = new User(5, "成吉思汗", "123456");
        //users[5]是null  --- 会影响排序
        System.out.println("排序前" + Arrays.toString(users));
        //开始排序
        //默认是按照id排序,因为我就是那样赋值的。
        //按姓名排  对应String类
        //按照id排 对应Integer类
        //按照id倒序


        //开始我的错误写法,没有理解obj1是什么,obj就是数组的元素。
        //也就是user对象,obj2-obj1这不行,不符合要求
        //应该是拿到数组元素后,调用数组的方法,得到ID属性
        //然后比较ID属性大小。这个思路有点像用对象数组遍历
        Arrays.sort(users, new Comparator() {
            @Override
            public int compare(User obj1, User obj2) {
                //排除null
                if (obj1 == null) {
                    if (obj2 == null) {
                        return 0;
                    }
                    return 1;
                }
                if (obj2 == null) {
                    return -1;
                }
                return obj2.getId() - obj1.getId();
            }
        });

        //对象数组遍历,我使用for in语句
        for (User user : users) {
            //得到user元素了
            //我可以用user对象输出
            if (user == null) {
                continue;
            }
            System.out.printf("姓名:%s,密码:%s%n", user.getName(), user.getPwd());
        }

        //总结,刚开始我没有转过来弯
        //我的理解是
        //在重写的方法中,方法参数就是obj1,obj2。它们的类型是万能的,可以装下任何类型
        //类似Object,var关键字
        //即,我知道我拿到了数组元素。
        // 我想比较数值元素的大小,那么就应该想好怎么用拿到的元素。
        //不就是用数值元素的一种值的比较
        //拿到元素就可以比较元素大小+我知道你是在参数中给我了数组元素 --- 我觉得这是一种设计思想

        //以下是我的错误写法
        //        Arrays.sort(users,(obj1,obj2)->obj2-obj1);
//        Arrays.sort(users,(obj1,obj2)->obj2.getId()-obj1.getId());
        

        //按照user的姓名首字母排序,
        Arrays.sort(users, new Comparator() {
            @Override
            public int compare(User obj1, User obj2) {
                if (obj1 == null) {
                    if (obj2 == null) {
                        return 0;
                    }
                    return 1;
                }
                if (obj2 == null) {
                    return -1;
                }
                return obj2.getName().charAt(0) - obj1.getName().charAt(0);
            }
        });

        System.out.println(Arrays.toString(users));
    }

    //最后的最后为了探究Arrays数组的sort 公共静态方法是怎么具体实现的,所以我把细节我做了探究
    public static void myTestArraysSort() {


        Integer[] integers = new Integer[]{23, 11, 88, 45, 108, 55, 34, 200, 90};

        Arrays.sort(integers, new Comparator() {
            @Override
            public int compare(Integer obj1, Integer obj2) {
                System.out.printf("obj1=%d,obj2=%d%n", obj1, obj2);
                return obj1 - obj2;
            }

        });
        //结果
//        obj1=11,obj2=23
//        obj1=88,obj2=11
//        obj1=88,obj2=23
//        obj1=45,obj2=23
//        obj1=45,obj2=88
//        obj1=108,obj2=45
//        obj1=108,obj2=88
//        obj1=55,obj2=45
//        obj1=55,obj2=108
//        obj1=55,obj2=88
//        obj1=34,obj2=55
//        obj1=34,obj2=23
//        obj1=34,obj2=45
//        obj1=200,obj2=45
//        obj1=200,obj2=88
//        obj1=200,obj2=108
//        obj1=90,obj2=55
//        obj1=90,obj2=108
//        obj1=90,obj2=88

        //分析 第1次 11和23比较  排好了 11 23
        //分析 第2次 88和11比较
        //分析 第3次 88和23比较   排好了 11 23 88
        //分析 第4次 45和23比较   2分+插入排序  中间+1找  发现比23大
        //分析 第5次 45和88比较   排好了 11 23 45 88
        //分析 第6次 108和45比较  中间+1, 发现比45大
        //分析 第7次 108和88比较 排好了 11 23 45 88 108
        //... 观看上面结果

        System.out.println(Arrays.toString(integers));//[11, 23, 34, 45, 55, 88, 90, 108, 200]升序

        //结论
        //1、方法参数是插入排序中带比较的元素,第一个参数是每次待排的元素,从下标1开始(第二个元素)。
        //2、如果返回值大于0,那么obj1在obj2后面
        //3、如果返回值小于0,那么obj1在obj2前面,
        //例子最小的数去找位置时(obj1),它小于每一个obj2, 返回值 obj1-obj2(<0)则是正序,
        //例子最小的数去找位置时(obj1),它小于每一个obj2, 返回值 obj2-obj1(>0)则是倒序,
        //4、用二分法定位,排到第一个或最后一个位置结束。 二分法可以减少查找次数
        //参数代表每次22比较的元素,返回值正负决定放的位置。
    }
}

//我的自定义类就放在这里,就是练习而已
//只能是缺省的class
//不能有main方法
class User {
    public User() {
    }

    public User(int id, String name, String pwd) {
        this.id = id;
        this.name = name;
        this.pwd = pwd;
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public String getPwd() {
        return pwd;
    }

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

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

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    private int id;
    private String name;
    private String pwd;

    @Override
    public String toString() {
        return "姓名:" + name + "密码:" + pwd;
    }
}
转载请注明:文章转载自 www.051e.com
本文地址:http://www.051e.com/it/956673.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 ©2023-2025 051e.com

ICP备案号:京ICP备12030808号