数组都clone问题,求解释

最近看一本书叫《改善java程序的151个建议》,发现这么一个方法。

 public static int max(int[] data) {
        Arrays.sort(data.clone()); //秒处
        return data[data.length - 1]
 }

这个方法的意图是找到数组中最大的一个数,为什么排序的是克隆对象呢,
因为这个方法的目的是取最大数,通过克隆对象去取的话,不改变原有数组的结构,
可是读者发现这个方法有问题,排序的是克隆对象,取值却还是从原来的数组中取.
请教大家,这个方法应该到底怎么写。

     public static int max(int[] data) {
         int[] newData = data.clone();
     Arrays.sort(newData);
     return newData[newData.length - 1];
     }

这是没效率的方法,不是反面教材?

 public class Util {
     public static int max(int[] data) {
         if (0 == data.length) return Integer.MIN_VALUE;
         int[] newData = data.clone();
     Arrays.sort(newData); //秒处
     return newData[newData.length - 1];
     }

     public static int getMax(int[] data) {
         if (0 == data.length) return Integer.MIN_VALUE;
         int maxVal = data[0];
         for (int i = 1; i < data.length; i++) {
             if (data[i] > maxVal) {
                 maxVal = data[i];
             }
         }
         return maxVal;
     }

     public static void main(String[] args) {
         final int NUMBER = 5000;
         final int TEST_NUM = 10000;
         int arr[] = new int[NUMBER];

         for (int i = 0; i < NUMBER; i++) {
             if (i % 2 == 1) arr[i] = i - 1;
             else arr[i] = i + 1;
         }

         long v1 = 0;
         long v2 = 0;
         long startTime = System.currentTimeMillis();

         for (int j = 0; j < TEST_NUM; j++) {
             v1 += max(arr);
         }

         long t1 = System.currentTimeMillis();

         for (int j = 0; j < TEST_NUM; j++) {
             v2 += getMax(arr);
         }       

         long t2 = System.currentTimeMillis();

         System.out.println("v1:" + v1 + ", time:" + (t1 - startTime));
         System.out.println("v2:" + v2 + ", time:" + (t2 - t1));
     }
}

输出:

v1:49990000, time:652
v2:49990000, time:61

时间差10倍,所以别随便信书上说的1万以下差别不大。

int max = data[0];
for (int i = 1; i < data.length; ++i)
if (data[i] > max) max = data[i];

首先我要解释一点,就是,保持程序的正确性,维持程序的简洁性,是作为程序员的第一要务

Don’t Cut Yourself: Code Optimization as a Double-Edged Sword。中文翻译:过早优化是万恶之源。
代码优化的好处多多,但是这并不意味着所有的代码都需要进行优化,有时过度的优化反而适得其反——费时、费力、不讨好。
“现代计算机科学的鼻祖”Donald Knuth曾说过“过早的优化是万恶之源”,因为:让正确的程序更快,要比让快速的程序正确容易得多。文中讲了7个原则,简单罗列如下:
1. 究竟要优化什么?
2. 选择一个正确的优化指标
3. 优化在刀刃上
4. 优化层次越高越好
5. 不要过早优化
6. 依赖性能分析,而不是直觉
7. 优化不是万金油

因此脱离了上下文,不要去讨论代码的效率。
以你的程序为例,我们首先要搞清楚的是,这个寻找最大数的代码,在整个程序中是否是在热区上。所谓热区,就是说,这个函数是频繁被调用么?或者是程序中耗时最多的代码么?大多数情况下,你写了一个程序(我说的是有一定规模的商业软件),90%的代码,其实都是几乎不被调用的,而只有10%的代码是反复调用,耗时巨大的。在不是热区的代码上“优化”,哪怕程序性能提高了1亿倍,但是程序的运行时间也只能压缩10%。
然而这么做付出的代价是,程序变得面目全非,到处都是各种奇怪的技巧,难以修改。项目开发进度大大增加。甚至为了性能,引入bug,连正确性都没有办法保证。

我没有你说的那本书,也没有看到你代码的上下文。
但是如果这个代码不位于热区,并不需要苛求性能的话,我觉得这么写很清晰,体现了作者明白的意图,就是寻找最大数,并且通过克隆避免对原始数据的顺序的修改嘛。当然,我们有更快的做法,问题是一个会武功的人,需要在吃饭的时候也把筷子当作武器耍弄一番么?

public static int max(int[] data) {
Arrays.sort(data.clone()); //秒处
return data[data.length - 1];
}

原因:我把data.clone()命名为cloneData
cloneData相当于复制了一份data数组,而你是对cloneData数组进行排序的,但是返回的却是data数组中的数据。你应该返回cloneData中的数据才是你想要的结果