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

标签 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();
}

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

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

最佳答案

如果你正在使用 ,你可以在 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() 对于小数据集的效率可能较低。因此不要过早进行优化。首先衡量您的代码,如果确实存在性能问题,请尝试调查问题所在和原因。

关于java - 当 V 是 T 中的属性对象时,如何将数组 T[] 转换为 V[],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27588663/

相关文章:

java - logj4 的备份文件每日滚动限制

php - foreach 一个数组来检查一个键的值是否不为空

python - 迭代索引效率子集

c# - 接受 SSL 套接字时性能非常差

c# - x64 与 x86 性能考虑因素.Net

java - 如何在tomcat的服务器端进行调试?

java - 尝试解密指纹 API 密码时出现 BadPaddingException

java - 将 json 对象反序列化为具有与 ArrayList 不同行为的列表的最佳方法是什么

arrays - swift 3 : Split string into Array of Int

javascript - 在 LazyJS 中的哪个位置