【问题标题】:Improving the performance of merging two ArrayLists提高合并两个 ArrayList 的性能
【发布时间】:2013-09-30 12:00:01
【问题描述】:

我将两个ArrayLists 与以下代码合并。该代码正在运行并给我想要的结果,但我想要一个更高效的版本。以下是条件。

  1. 方法接受两个列表,并且两个列表的元素都按降序排列 (5,4,3,2)
  2. 方法接受一个整数来决定生成的ArrayList 的大小。
  3. 第一个输入列表的大小永远不会大于生成的 ArrayList 的大小。

代码:

public ArrayList<Integer> mergeList(ArrayList<Integer> first,ArrayList<Integer> second, int n){
    //case 1: when both list are null.
    if(first == null && second == null )
        return null;
    //case 2: when first list is null but second list have elements
    else if( first == null && second != null){
        return second.size() >=n ? new ArrayList<Integer>(second.subList(0, n)) : second;
    }
    //case 3: when first list have record and second list is null
    else if(first != null && second == null){
        return first;
    }
    //case 4: when both list have elements 
    else {
        first.addAll(second);
        Collections.sort(first);
        Collections.reverse(first);
        return first.size()>=n ? new ArrayList<Integer>(first.subList(0, n)) : first;
    }
}

}

【问题讨论】:

  • 这太复杂了。 ArrayList 按需扩展,因此无需预先分配(不需要参数int n);您应该只在开始时分配一次结果列表。我认为这里的目标是编写适当的合并。连接列表和排序将不是最好的解决方案。如果由于某种原因您仍想这样做,请按降序排序,这样您就不必颠倒列表。
  • @JimGarrison 参数 n 是要求的一部分,所以我无法避免,但我接受了您的建议并更新了我的代码。最新代码已上传。
  • 结果列表是否也需要倒序排列?在输入或结果中是否允许重复?

标签: java data-structures collections arraylist merge


【解决方案1】:

这取决于您所说的“更高效”是什么意思。

在什么方面?内存、CPU、可读性?

根据您上面的代码,我做出以下假设:

  • 可读性比没有任何分析测量/要求的纯粹性能/内存消耗更重要“程序优化的第一条规则:不要这样做。程序优化的第二条规则(仅供专家使用!):不要这样做还没完成。” — 迈克尔 A.杰克逊
  • 首选 null 对象模式而不是返回 null
  • 重复元素是可取的/必需的
  • 使用Comparator 执行反向操作 排序

private List<Integer> mergeList(List<Integer> list1, List<Integer> list2, final int newSize) {

    // Enforce null object pattern
    if (list1 == null) {
        list1 = Collections.emptyList();
    }
    if (list2 == null) {
        list2 = Collections.emptyList();
    }

    // If duplicates are not desirable, a TreeSet would perform automatic sorting.
    List<Integer> result = new ArrayList<Integer>(list1);
    result.addAll(list2);

    Comparator<Integer> reverseSortComparator = new Comparator<Integer>() {

        @Override
        public int compare(final Integer o1, final Integer o2) {
            return o2.compareTo(o1);
        }
    };

    Collections.sort(result, reverseSortComparator);

    if (result.size() > newSize) {
        return result.subList(0, newSize);
    } else {
        return result;
    }
}

【讨论】:

  • 非常感谢。这就是我想要实现的目标
【解决方案2】:

您似乎正在尝试保留firstsecond 的内容。如果你不是,那么这对你来说会很好,并且会让你的代码更快、更易读:

public ArrayList<Integer> mergeList(ArrayList<Integer> first,ArrayList<Integer> second, int maxLength){

    //case 1: when both list are null.
    if(first == null && second == null )
        return null;
    //case 2: when first list is null but second list have elements
    else if( first == null && second != null){
        return second;
    }
    //case 3: when first list have record and second list is null
    else if(first != null && second == null){
        return first;
    }
    //case 4: when both list have elements 
    else if(first != null && second != null){
        first.addAll(second);
        Collections.sort(first); //want to merge these two line into one
        Collections.reverse(first);
    }
    return (ArrayList) first.size() > maxLength ? first.subList(0, n) : first;
}

之所以更快是因为对于每个addAll(),Java 必须遍历所有项目,将它们复制到tempList。我保留了Collections.reverse 调用,因为您似乎需要将数据按反向排序。

【讨论】:

  • 不,我不想保留第一个和第二个的内容,但我确实想返回大小为 n 的列表,我的列表的第三个参数。
  • @Ashish,我重新添加了截断步骤。这将修剪列表中的最小元素,使列表长度不超过maxLength
  • 谢谢,但是 subList(0,n) 将返回 List 而不是 arraylist。
  • @Ashish,ArrayList "isa" List。只需将其转换回ArrayList
  • 我试过了,虽然我已经用你想说的话更新了我的代码
猜你喜欢
  • 2019-09-17
  • 1970-01-01
  • 2017-04-13
  • 1970-01-01
  • 2017-05-15
  • 2017-04-11
  • 1970-01-01
  • 1970-01-01
  • 2017-08-28
相关资源
最近更新 更多