当V是T中的属性对象时,如何将数组T []转换为V []

时间:2014-12-21 10:51:19

标签: java arrays performance iteration

这样做的一种简单方法是迭代数组T []并分配其类型为V的字段并填充新数组。 但是,是否有更高效/更优雅的方式(可能是Java中的内置功能)?

编辑:  我试过的代码:

Locale[] locs = Locale.getAvailableLocales();
String[] coutries = new String[locs.length] ;
for (int i = 0; i < locs.length; i++) {
    coutries[i] = locs[i].getDisplayCountry();
}

EDIT2: 对于大约200个元素的小数组,似乎对流使用map操作更快,这是第二种方法:

coutries = Arrays.stream(locs).map(Locale -> Locale.getDisplayCountry()).toArray(String[]::new);

1 个答案:

答案 0 :(得分:7)

如果您使用,则可以使用map上的Stream操作:

V[] arr = Arrays.stream(arrayOfTypeT).map(t -> t.v).toArray(V[]::new);

甚至更好(如果封装好)

V[] arr = Arrays.stream(arrayOfTypeT).map(T::getV).toArray(V[]::new);

<小时/> 所以这是基准(注意我不是JMH大师):

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class Benchmark {   

    static Integer[] ints = IntStream.range(0, 1_000_000).boxed().toArray(Integer[]::new);

    public static void main(String... args) throws RunnerException {
        Options opt = new OptionsBuilder()
        .include(".*" + Benchmark.class.getSimpleName() + ".*")
        .forks(1)
        .warmupIterations(20)
        .build();

        new Runner(opt).run();
    }

    @GenerateMicroBenchmark
    public void standardForLoop() {
        final String[] arr = new String[ints.length];
        for (int i = 0; i < ints.length; i++) {
            arr[i] = String.valueOf(ints[i]);
        }
    }

    @GenerateMicroBenchmark
    public void forEachLoop() {
        final String[] arr = new String[ints.length];
        for (int i : ints) {
            arr[i] = String.valueOf(i);
        }
    }

    @GenerateMicroBenchmark
    public void streamMapOperation() {
        @SuppressWarnings("unused")
        String[] arr = Arrays.stream(ints).map(String::valueOf).toArray(String[]::new);
    }

    @GenerateMicroBenchmark
    public void streamParallelMapOperation() {
        @SuppressWarnings("unused")
        String[] arr = Arrays.stream(ints).parallel().map(String::valueOf).toArray(String[]::new);
    }    
}

结果:

Benchmark                                Mode   Samples         Mean   Mean error    Units
b.Benchmark.forEachLoop                  avgt        20       58,455        2,359    ms/op
b.Benchmark.standardForLoop              avgt        20       59,214        2,415    ms/op
b.Benchmark.streamMapOperation           avgt        20       62,877        2,887    ms/op
b.Benchmark.streamParallelMapOperation   avgt        20       40,171        6,456    ms/op

如您所见,对于庞大的数据集,标准循环和流方法之间没有太大区别。但是使用流方法,您可以轻松调用parallel(),这使得计算效率稍高(当然,您可以编写自己的多线程实用程序来执行此操作,但这需要您做一些工作)。

请注意,由于线程设置,同步等原因,parallel()对小型数据集的效率可能较低。因此,不要过早优化。首先测量您的代码,如果确实存在性能问题,请尝试调查其中的位置和原因。