论坛首页 Java企业应用论坛

给大家娱乐一下,优化一个简单的算法

浏览 10174 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2005-03-16  
我先声明,这个算法本身简单,但要优化,就不是那么简单了。为啥,因为它太简单了。

要求是返回一个Comparator,该Comparator能比较两个byte数组的大小。byte数组大小的定义是:数组中每一个byte都是无符号的整数。即0xff不是-128,而是255;按数组中byte的顺序比较对应byte,如果相等,则比较下一个,如果不等,则byte数值大的数组为大。

byte数组的长度可以肯定是在1-50之间。

byte数组的长度在 getByteArrayComparator方法的参数中可以得到,也就是 int byteArrayLength.

这是我工作中遇到的一个真实问题。下面的code是我最初的算法。由于这个算法在某种情况下成为我程序中的瓶颈,因此我花了很大力气优化它,一共优化了三次。优化三次后的算法应该是非常快的算法了。

大家可以畅所欲言。任何理论上的算法优化都欢迎,但不要谈什么C啊汇编啊的。

public Comparator getByteArrayComparator(int  byteArrayLength);
{
    return new ByteArrayComparator();;
}

class ByteArrayComparator implements Comparator
{
    public int compare(Object o1,Object o2);
    {
        byte[] b1=(byte[]);o1;
        byte[] b2=(byte[]);o2;
        for(int =0;i<b1.length;i++);
        {
           int  s1=b1[i]&0xff
           int  s2=b2[i]&0xff
           if(s1>s2);
             return 1;
           else if(s1<s2);
              return -1;
         }
         return 0;
    }
}
   发表时间:2005-03-16  
octfor 写道
我先声明,这个算法本身简单,但要优化,就不是那么简单了。为啥,因为它太简单了。

要求是返回一个Comparator,该Comparator能比较两个byte数组的大小。byte数组大小的定义是:数组中每一个byte都是无符号的整数。即0xff不是-128,而是255;按数组中byte的顺序比较对应byte,如果相等,则比较下一个,如果不等,则byte数值大的数组为大。

byte数组的长度可以肯定是在1-50之间。

byte数组的长度在 getByteArrayComparator方法的参数中可以得到,也就是 int byteArrayLength.

这是我工作中遇到的一个真实问题。下面的code是我最初的算法。由于这个算法在某种情况下成为我程序中的瓶颈,因此我花了很大力气优化它,一共优化了三次。优化三次后的算法应该是非常快的算法了。

大家可以畅所欲言。任何理论上的算法优化都欢迎,但不要谈什么C啊汇编啊的。

public Comparator getByteArrayComparator(int  byteArrayLength);
{
    return new ByteArrayComparator();;
}

class ByteArrayComparator implements Comparator
{
    public int compare(Object o1,Object o2);
    {
        byte[] b1=(byte[]);o1;
        byte[] b2=(byte[]);o2;
        for(int =0;i<b1.length;i++);
        {
           int  s1=b1[i]&0xff
           int  s2=b2[i]&0xff
           if(s1>s2);
             return 1;
           else if(s1<s2);
              return -1;
         }
         return 0;
    }
}


给出一个思路,没有code test 过。

	public int compare(Object o1,Object o2);
	{
		byte[] b1=(byte[]);o1;
		byte[] b2=(byte[]);o2;
		/*for(int i=0;i<b1.length;i++);
		{
		   int  s1=b1[i]&0xff;
		   int  s2=b2[i]&0xff;
		   if(s1>s2);
			 return 1;
		   else if(s1<s2);
			  return -1;
		 }
		 return 0;*/
		BigInteger bi1=new BigInteger(b1);;
		BigInteger bi2=new BigInteger(b2);;
		return bi1.compareTo(bi2);;
	}

前提,两个数组长度必须一致。
0 请登录后投票
   发表时间:2005-03-16  
几点疑问:
这两个数组长度一样吗?
byteArrayLength拿来干吗用,不是可以通过length来取数组长度吗?
某种情况是指哪种情况?

最后问一句, 既然都是正数,为啥要用byte[]而不用char[]呢?
当然char是16位的而byte是8位的,但是byte有正负啊.
0 请登录后投票
   发表时间:2005-03-16  
BigInteger的内部比较方法:

    /*
     * Returns -1, 0 or +1 as big-endian unsigned int array arg1 is
     * less than, equal to, or greater than arg2.
     */
    private static int intArrayCmp(int[] arg1, int[] arg2) {
if (arg1.length &lt; arg2.length)
    return -1;
if (arg1.length &gt; arg2.length)
    return 1;

// Argument lengths are equal; compare the values
for (int i=0; i&lt;arg1.length; i++) {
    long b1 = arg1[i] & LONG_MASK;
    long b2 = arg2[i] & LONG_MASK;
    if (b1 &lt; b2)
return -1;
    if (b1 &gt; b2)
return 1;
}
return 0;
    }

也是逐个比较。

不知道 long, int, short, char, byte 等类型的比较速度,差别大不大。

这种顺序比较的效率,确实值得关注。我有一个帖子,讨论QueryKey的SQL String 的比较速度。不过我用的是拆分SQL本身,和这个算法无关了。
很期待大家的讨论,也期待楼主一步步展示优化的过程。:-)
0 请登录后投票
   发表时间:2005-03-16  
firebody 写道

给出一个思路,没有code test 过。
		BigInteger bi1=new BigInteger(b1);;
		BigInteger bi2=new BigInteger(b2);;
		return bi1.compareTo(bi2);;
	}

前提,两个数组长度必须一致。

数组的长度是一致的,也就是参数中int byteArrayLength的值。
不过,我说老火,你一句new BigInteger,我原来的程序就可以运行好几次了。

mochow 写道
几点疑问:
这两个数组长度一样吗?
byteArrayLength拿来干吗用,不是可以通过length来取数组长度吗?
某种情况是指哪种情况?

最后问一句, 既然都是正数,为啥要用byte[]而不用char[]呢?
当然char是16位的而byte是8位的,但是byte有正负啊.

数组长度一致。
某些情况是指我程序在收到某些客户计算请求时,Comparator.compare要运行tens of millions次

1.因为byte省空间。2.因为要比较的数据本来就是byte数组。

buaawhl 写道


不知道 long, int, short, char, byte 等类型的比较速度,差别大不大。

这个测试我做过,差别还是满大的。int最快,byte,short,稍慢,long是最慢了,大约比int慢三四倍。
0 请登录后投票
   发表时间:2005-03-16  
可以这样比较:
1,先判断是否相等,如果不等则继续到2;
2,再判断如果符号不同,是一个正一个负,那么负的大
3,如果符号相同,那么取绝对值比较,绝对值大的就大,这一步也可以细分为都是正的和都是负的两种分别来处理,看哪个的效率高.
0 请登录后投票
   发表时间:2005-03-16  
mochow 写道
可以这样比较:
1,先判断是否相等,如果不等则继续到2;
2,再判断如果符号不同,是一个正一个负,那么负的大
3,如果符号相同,那么取绝对值比较,绝对值大的就大

1不错。
2,3怎么做?
mochow,这个代码很简单的,你就写两句吧。有代码大家好讨论点。
0 请登录后投票
   发表时间:2005-03-16  
最后两步还可以改进一下,改为如果不相等,那么只用判断如果都是正的则大的大,
否则小的大.
    public int compareTo1(Object o1,Object o2); 
       { 
           
           byte[] b1 = (byte[]); o1;
           byte[] b2 = (byte[]); o2;
           for(int i=0;i<b1.length;i++); { 
               if(b1[i]==b2[i]);{
                   continue;
               }
               else if(b1[i]>0&&b2[i]>0);{
                       if(b1[i]>b2[i]);{
                           return 1;
                       }
                       else{
                           return -1;
                       }
                }
                else{
                    if (b1[i] > b2[i]); {
                        return -1;
                    }
                    else{
                        return 1;
                    }
                }
           }
           return 0;
       }

0 请登录后投票
   发表时间:2005-03-16  
引用
数组中每一个byte都是无符号的整数。
0 请登录后投票
   发表时间:2005-03-16  
good.mochow.
在我的机器上,我测试了一下。
楼顶我的方法所用时间是1472,你的是1232.优化了大约10%。
我的第一次优化和你的差不多,大约是1151。
  class byte3 implements Comparator
  {
    public int compare(Object o1,Object o2);
    {
      byte[] b1=(byte[]);o1;
      byte[] b2=(byte[]);o2;
      for(int i=0;i<b1.length;i++);
      {
        if(b1[i]!=b2[i]); 
          return (b1[i]&0xff);-(b2[i]&0xff);;
      }
     return 0; 
    }
  }


我最终的优化版本时间是641.
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics