tags:

views:

191

answers:

3

I have an interface DataSeries with a method

int[] getRawData();

For various reasons (primarily because I'm using this with MATLAB, and MATLAB handles int[] well) I need to return an array rather than a List.

I don't want my implementing classes to return the int[] array because it is mutable. What is the most efficient way to copy an int[] array (sizes in the 1000-1000000 length range) ? Is it clone()?

+1  A: 

http://www.javapractices.com/topic/TopicAction.do?Id=3

the numbers will likely be different depending on your specs, but seems clone is the best choice.

jonathanasdf
Whoever wrote that does not understand microbenchmarking.
Kevin Bourrillion
+5  A: 

The only alternative is Arrays#copyOf() (which uses System#arrayCopy() under the hoods).

Just test it.

package com.stackoverflow.q2830456;

import java.util.Arrays;
import java.util.Random;

public class Test {

    public static void main(String[] args) throws Exception {
        Random random = new Random();
        int[] ints = new int[100000];
        for (int i = 0; i < ints.length; ints[i++] = random.nextInt());

        long st = System.currentTimeMillis();
        test1(ints);
        System.out.println(System.currentTimeMillis() - st);

        st = System.currentTimeMillis();
        test2(ints);
        System.out.println(System.currentTimeMillis() - st);
    }

    static void test1(int[] ints) {
        for (int i = 0; i < ints.length; i++) {
            ints.clone();
        }
    }

    static void test2(int[] ints) {
        for (int i = 0; i < ints.length; i++) {
            Arrays.copyOf(ints, ints.length);
        }
    }

}
20203
20131

and when test1() and test2() are swapped:

20157
20275

The difference is negligible. I'd say, just go for clone() since that is better readable and Arrays#copyOf() is Java 6 only.

Note: actual results may depend on platform and JVM used, this was tested at an Dell Latitude E5500 with Intel P8400, 4GB PC2-6400 RAM, WinXP, JDK 1.6.0_17_b04

BalusC
Really weird... the article I posted has copyOf clocking in at 2x slower than clone.. Sadly I don't have JDK on this machine or I would be able to run a test myself. But anyways +1 for making your own test.
jonathanasdf
Beat me to it. Was just about to run my own test. @BalusC, what if it is run with Random values? Don't expect it would really make any difference, but the array you are cloning is uniformly distributed.
Finbarr
@jonathan: May depend on platform and JVM used.
BalusC
@Finbarr: filling every int with `Random#nextint()` yields `20046` and `20032` ms. No noticeable difference.
BalusC
now you're forgetting import java.util.Random; :) Downloaded jdk and tested - 16140 and 17047 on my computer. Seems clone is faster for me... but not 2x as fast.
jonathanasdf
suggest `static void test1(int[] ints, int reps) { for (int i = 0; i < reps; i++) { ints.clone(); } }`(and similarly for test2)
Jason S
To all micro-benchmarkers ... **beware of JVM warmup effects**. Wrap your microbenchmark in a method and call it in a loop a few times and ignore results prior to stabilization.
Stephen C
@Stephen: that's exactly the reason why I added a result when the methods are swapped.
BalusC
@BalusC - you miss my point. You need to call `test1` and `test2` multiple times.
Stephen C
Guys, microbenchmarking is a LOT harder than this. I would not trust these results. http://code.google.com/p/caliper/wiki/JavaMicrobenchmarks
Kevin Bourrillion
+5  A: 
  1. No one ever solved their app's performance problems by going through and changing arraycopy() calls to clone() or vice versa.

  2. There is no one definitive answer to this question. It isn't just that it might be different on different VMs, versions, operating systems and hardware: it really is different.

  3. I benchmarked it anyway, on a very recent OpenJDK (on a recent ubuntu) and found that arraycopy is much faster. So is this my answer to you? NO! Because if it proves to be true, there's a bug with the intrinsification of Arrays.copyOf, and that bug will likely get fixed, so this information is only transient to you.

Kevin Bourrillion