java学习-排序及加密签名时数据排序方式

排序有两种,

基本数据类型的包装类Integer, Float, Double,Long,Byte等都实现的Comparable接口,用于列表List或数组arrays的排序

Comparable<Integer>接口方法的实现,对象列表的升序降序接口

我们通过重写改接口方法,可以对列表进行升序或降序排列。

public int compareTo(T o);

This interface imposes a total ordering on the objects of each class that implements it. This ordering is referred to as the class‘s natural ordering, and the class‘s compareTo method is referred to as its natural comparison method.

此接口对实现它的每个类的对象强加一个默认排序。这种排序被称为类的自然排序,类的compareTo方法被称为其自然比较方法。

Lists (and arrays) of objects that implement this interface can be sorted automatically by Collections.sort (and Arrays.sort).

只有实现的这个接口的对象list列表或array数组才可以使用sort方法让列表或数组的元素被自动排序

只需要实现compareTo()方法即可

public int compareTo(){}这个比较方法,,如果要将对象列表进行升序排序,则第i个元素和第i+1元素  要满足a[i]>a[i+1]  返回1   a[i]<a[i+1] 返回-1   a[i]=a[i+1]   返回0

如果要将对象列表进行降序排序  要满足 a[i]>a[i+1] 返回-1   a[i]<a[i+1] 返回1 a[i]=a[i+1] 返回0
Collections.sort方法实现的就是按照此比较的东西排列
升序(从小到大):
if(price < o.price){
    return -1;
}
if(price > o.price){
   return 1;
}
降序(从大到小):
if(price < o.price){
   return 1;
}
if(price > o.price){
   return -1;
}

    //将对象按价格进行升序排序
    @Override
    public int compareTo(flower o) {
        //首先比较price,如果price相同返回0
        if(price < o.price){
            return -1;
        }
        if(price > o.price){
            return 1;
        }

        return 0;
    }

为什么升序  返回值为1时,是n的值要大于n+1的值,而返回值为-1时n的值要小于n+1呢?

这个要查看源码才可以知道原理。(不好奇的可以不看哦^~^)

由于这个List.sort()这个排序方法时使用二分排序,源码如下,

private static void binarySort(Object[] a, int lo, int hi, int start) {
        assert lo <= start && start <= hi;
        if (start == lo)
            start++;
        for ( ; start < hi; start++) {
            Comparable pivot = (Comparable) a[start];

            // Set left (and right) to the index where a[start] (pivot) belongs
            int left = lo;
            int right = start;
            assert left <= right;
            /*
             * Invariants:
             *   pivot >= all in [lo, left).
             *   pivot <  all in [right, start).
             */
            while (left < right) {
                int mid = (left + right) >>> 1;
                if (pivot.compareTo(a[mid]) < 0)
                    right = mid;
                else
                    left = mid + 1;
            }
            assert left == right;

            /*
             * The invariants still hold: pivot >= all in [lo, left) and
             * pivot < all in [left, start), so pivot belongs at left.  Note
             * that if there are elements equal to pivot, left points to the
             * first slot after them -- that‘s why this sort is stable.
             * Slide elements over to make room for pivot.
             */
            int n = start - left;  // The number of elements to move
            // Switch is just an optimization for arraycopy in default case
            switch (n) {
                case 2:  a[left + 2] = a[left + 1];
                case 1:  a[left + 1] = a[left];
                         break;
                default: System.arraycopy(a, left, a, left + 1, n);
            }
            a[left] = pivot;
        }
    }

            while (left < right) {
                int mid = (left + right) >>> 1;
                if (pivot.compareTo(a[mid]) < 0)
                    right = mid;
                else
                    left = mid + 1;
            }

这个值是和已排序的数据的中间的数据进行比较,provot.compareTo(a[mid])

注意看,上面的a[mid]是作为比较方法的参数。

当小于0,也就是值为-1时,是我们要插入的数据作为调用方,

小于0时,该数据插入到前面,

大于0时,数据插入到后面

思维惯性以为升序就是第一个元素比第二个元素小。obj1.compareTo(Object obj2)

即obj1=2是第一个元素,obj2=8是第二个元素

那么我们升序时,如果obj1小于obj2,返回值为-1,则会将obj2插入到obj1前面,,排序前【2, 8】这样排序完后却变成了,,【8, 2】

这跟我们想要的升序数据不一样,

原因是java的二分法进行比较了是,,obj2.compareTo(obj1),,与我们想的刚好相反,

所以我们返回的值取反就可以变成升序了,

如这个消费类,,只给出部分代码

public class ConsumInfo implements Comparable<ConsumInfo> {
    public double price;   public String name;  public Consuminfo(double price, String name){   this.price = price;   this.name = name;  }

   @Override
    public int compareTo(ConsumInfo o) {
        //首先比较price,如果price相同
        if(price < o.price){
            return -1;
        }
        if(price > o.price){
            return 1;
        }

        return 0;
    }

}

    ConsumInfo consumInfo1 = new ConsumInfo("consumInfo1", 400.0);
       ConsumInfo consumInfo2 = new ConsumInfo("consumInfo2", 200.0);
    List<ConsumInfo> list = new ArrayList<ConsumInfo>();
       list.add(consumInfo1);
       list.add(consumInfo2);

    System.out.println("排序前:");
    for(ConsumInfo consumInfo : list ){
            System.out.println(consumInfo);
        }

    Collections.sort(list);//排序
    System.out.println("排序后:");//排序后
       for(ConsumInfo consumInfo :list){
            System.out.println(consumInfo);
       }

控制台输出信息为:

排序前:
ConsumInfo [name=consumInfo1, price=400.0]
ConsumInfo [name=consumInfo2, price=200.0]
排序后:
ConsumInfo [name=consumInfo2, price=200.0]
ConsumInfo [name=consumInfo1, price=400.0]

上面是最简单的两个元素进行排序,

第一次,往已排序列表中插入第一个元素,即数组中只有一个已排好序的元素,a[0] = consumInfo1

第二次时,left为0,right为1,进入while循环中,

mid=0,privot=consumInfo2

即consumInfo2.comparTo(a[0])

当方法的返回值小于0时,consumInfo2会插入在consumInfo1之前,

大于0时,会在consumInfo1之后

进行比较时,consumInfo2.price<consumInfo1.price    返回值小于0,也就是consumInfo1的值比较大,插入在1之前

原文地址:https://www.cnblogs.com/gne-hwz/p/10175592.html

时间: 2024-11-08 21:47:21

java学习-排序及加密签名时数据排序方式的相关文章

Java虚拟机 - 结构原理与运行时数据区域

http://liuwangshu.cn/java/jvm/1-runtime-data-area.html 前言 本来计划要写Android内存优化的,觉得有必要在此之前介绍一下Java虚拟机的相关知识,Java虚拟机也并不是三言两语能够介绍完的,因此开了Java虚拟机系列,这一篇文章我们来学习Java虚拟机的结构原理与运行时数据区域. 1.Java虚拟机概述 Oracle官方定义的Java技术体系主要包括以下几个部分: Java程序设计语言 各种平台的Java虚拟机 Class文件格式 Ja

Java内存模型与JVM运行时数据区的区别

首先,这两者是完全不同的概念,绝对不能混为一谈. 1.什么是Java内存模型? Java内存模型是Java语言在多线程并发情况下对于共享变量读写(实际是共享变量对应的内存操作)的规范,主要是为了解决多线程可见性.原子性的问题,解决共享变量的多线程操作冲突问题. 多线程编程的普遍问题是: 所见非所得 无法肉眼检测程序的准确性 不同的运行平台表现不同 错误很难复现 故JVM规范规定了Java虚拟机对多线程内存操作的一些规则,主要集中体现在volatile和synchronized这两个关键字. vo

《深入理解Java虚拟机》笔记01 -- 运行时数据区

运行时数据区示意图 1. 程序计数器 占用一块较小的内存空间,它可以看作是当前线程所执行的字节码的行号指示器.主要用来记录线程执行到哪条语句了,分支.循环.跳转.异常处理.线程恢复等功能都需要依赖这个计数器来完成. 如果线程正在执行的是一个Java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址:如果正在执行的时Native方法,这个计数器值则为空.此内存区域是唯一一个在Java虚拟机规范中没有规定任何OutOfMemoryError情况的区域. 2. Java 虚拟机栈 线程私有,生命

Java虚拟机原理图解----JVM运行时数据区

     JVM运行时数据区(JVM Runtime Area) 其实就是指JVM在运行期间,其对计算机内存空间的划分和分配.本文将通过以下几个话题来讨论JVM运行时数据区. Topic 1. JVM运行时数据区 里有什么? Topic 2. 虚拟机栈 是什么?虚拟机栈 里有什么? Topic 3. 栈帧是什么?栈帧 里有什么? Topic 4. 方法区 是什么?方法区 里有什么? Topic 1.JVM运行时数据区里有什么? Topic 2. 虚拟机栈是什么?虚拟机栈里有什么? Topic 3

java虚拟机(1)--运行时数据区

一.              运行时数据区域 1.1 程序计数器 记录正在执行的虚拟机字节码指令的地址(如果正在执行的是本地方法则为空). 1.2 Java 虚拟机栈 每个 Java 方法在执行的同时会创建一个栈帧用于存储局部变量表.操作数栈.常量池引用等信息.从方法调用直至执行完成的过程,就对应着一个栈帧在 Java 虚拟机栈中入栈和出栈的过程. 可以通过 -Xss 这个虚拟机参数来指定每个线程的 Java 虚拟机栈内存大小: java -Xss512M HackTheJava 该区域可能抛

Java多个线程之间处理共享数据的方式

题目要求: 有4个线程,其中两个线程每次对x加1,另外两个每次对x减1,如何实现? 分析: x就是这4个线程要处理的共享数据,不同种线程有不同的处理方式,但操作的数据是共同的,联想到"窗口买票问题",但是卖票只是单纯的减. 所以,多个线程访问共享对象或数据的方式,先看,如果每个线程执行的代码相同,那么就可以使用同一个Runnable对象,这个对象中有被共享的数据,如买票问题. 如果每个线程执行的代码不同,肯定需要不用的Runnable对象,有两种方式实现这些不同的Runnable对象之

java学习笔记(二)之数据部分

数据类型 java数据类型 基本数据类型 数值型 整型byte/short/int/long   浮点型/double/float   字符型char     布尔型boolean 取值true  false         对象数据类型 类Class     接口 interface     数组array[]       类型 对象 位数 字节数 最小值 最大值 byte Byte 8    1 -128=2^7 127=2^7-1 short Short 16 2  -32768=2^15

java内存模型和jvm运行时数据区对应起来谈的疑惑

求解,要对一组数据分组,每组最多不能超过10条数据MYSQLREPLICATION中的EVENTSCHEDULER小结TP5为什么要取消模板引擎的模板主题设计怎么在控制器的构造函数里直接返回 初学Linux请问cp命令的正确写法TP5AJAX请求的地址不能识别{:URL('控制器/方法')}么TP5调用游标存储过程返回连接爆量错误求解创建有个性的对话框之MFC篇 'java'alreadyexists该怎么解决THINKPHPPHPEXCEL导入到数据库但是没有数据插入PHP全职工程师招聘在广州

java学习笔记 (2) —— Struts2类型转换、数据验证重要知识点

1.*Action.conversion-properties 如(point=com.test.Converter.PointListConverter) 具体操作类的配置文件 2.*Action.properties 如(invalid.fieldvalue.graduation=\u6bd5\u4e1a\u65e5\u671f\u8f93\u5165\u9519\u8bef) 具体字段错误提示信息的配置文件 2.struts.xml 中 <action name="register&