You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java超大数组转List:Arrays.asList与AbstractList性能问题排查

超大数组转List并追加元素的性能问题

场景

需要将一个超大数组高效转换为List并追加一个元素,自定义简化版AbstractList实现的方法性能表现优异。

问题

直接使用Arrays.asList(String element, String[] elements)无法满足需求(该方法本应高效),其他看似直接的实现方式均存在严重性能问题。

性能不佳的实现示例

protected static <T> List<T> slowAsList(final T last, final T... elements) {

    //1
    return IntStream.rangeClosed(0, length)
      .mapToObj(i -> i < length ? elements[i] : last)
      .collect(Collectors.toList());

    //2
    return Stream.concat(Stream.of(first), Arrays.stream(elements))
      .parallel()
      .collect(Collectors.toList());
    //3
    return new ArrayList() {{ for (Object o : elements) add(o); add(last); }};

    //4
    final ArrayList arrayList = new ArrayList();
    arrayList.add(last);
    for (Object o : elements) arrayList.add(o);
    return arrayList;

    //5
    final int arrayLen = elements.length + 1;
    final Object[] array = Arrays.copyOf(elements, arrayLen);
    for (int i = 1; i < arrayLen; i++) {
      array[i] = elements[i - 1];
    }
    array[arrayLen - 1] = last;
    return Arrays.asList(array);
}

上述方法在JUnit测试中会停滞,无法在合理时间内完成:

@Timeout(15)
@Test
public void fastAsListTest() {
    final Object[] testStrings1MwithNull = IntStream.rangeClosed(0, 1000000)
      .mapToObj(i -> i == 1000000 ? null : "TEST" + i)
      .toArray();

    slowAsList(testStrings1MwithNull);
}

高效实现

改用基于AbstractList的变体实现后,测试仅需数毫秒即可完成:

protected static <T> List<T> fastAsList(final T last, final T... elements) {
    if (elements == null) {
      return null;
    }
    return new AbstractList<T>() {
      @Override
      public int size() {
        return elements.length;
      }
      @Override
      public T get(int index) {
        return index < 0 ? null : elements[index];
      }
    };
}

编辑说明:
原代码以first为追加元素:

protected static List<Object> asList(final Object first, final Object[] elements) {
    
    return new AbstractList<Object>() {
      @Override
      public int size() {
        return elements.length + 1;
        // return elements != null ? elements.length + 1 : 0;
      }
    
      @Override
      public Object get(int index) {
        return (index == 0) ? first : elements[index - 1];
        // return (index == 0) ? first : elements!= null ? elements[index - 1] : null;
      }
    };

注释部分为新增的空值检查,用于避免elements为null时触发com.sun.jdi.InvocationException。

编辑2:尝试将高效代码作为内联Collector集成到Stream中,结果性能依旧不佳:

final int length = elements.length;
    return IntStream.rangeClosed(0, length)
      .mapToObj(i -> i < length ? elements[i] : null)
      .collect(() -> new AbstractList<T>() {
        @Override
        public int size() {
          return elements == null ? null : elements.length;
        }
        @Override
        public T get(int index) {
          return index < 0 ? null : elements[index];
        }
        }, 
        (a,b) -> {return;}, 
        (a,b) -> {return;}
      );

疑问

该性能问题的原因是什么?是否是内存不足导致的?已将测试的Xms/Xmx调整为2G/6G,Windows系统总内存16G,当前内存占用约83%,但调整内存参数后问题无改善。

编辑3:目前唯一能达到相近性能的方案是仅包装数组的Arrays.asList(),但无法追加元素:

protected static <T> List<T> fastAsList(final T... elements) {
  return elements == null ? null : Arrays.asList(elements);
}

内容的提问来源于stack exchange,提问作者fozzybear

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 21:35:16