【问题标题】:combine two lists in Java [duplicate]在Java中合并两个列表[重复]
【发布时间】:2013-10-10 18:37:20
【问题描述】:

我有两个参数数量相同的列表,我想要一种优雅组合它们的方式(不是连接) .

这是我目前(不太好)的做法(只是为了让你知道我想要做什么)。

    List<Double> list1 = ... // init here
    List<Double> list2 = ... // init here
    Function<Double, Double, Double> myFunc = ... // init here

    List<Double> ret = new ArrayList<Double>(size);

    for (int n = 0; n < size; ++n)
    {
        ret.add(func.apply(list1.get(n),
                           list2.get(n)));
    }
    return ret;

interface Function <X, Y, Z>
{
    Z apply(X arg1, Y arg2);
}

是否有一些现有的助手可以让我做类似的事情:

Lists.combine(list1, list2, myFunction);

例如,假设我有两个整数列表,并且我有函数f(x, y) = x * y)

我希望结果列表是(x[i] * y[i]) 的列表

具体来说,

list1 = {1, 2, 3, 4}
list2 = {2, 3, 4, 4}

result = {2, 6, 12, 15}

谢谢

【问题讨论】:

  • 不!这只是将它们压缩在一起,而不是改变它们
  • 假设我有两个整数列表,我希望结果列表是每个列表中两个元素的总和
  • 创建Function 匿名内部类比编写普通的for 循环需要更多的麻烦,而没有任何花哨的函数技术。真的,这是一个三行 for 循环,并不是特别复杂。
  • 如果您对这两个列表所做的事情非常复杂,或者您必须在程序中进行大量的梳理业务,但每次组合的方式都不同,该怎么办?您需要一种方法来一致地组合这两个列表,而不必知道如何处理每个元素的具体细节,不是吗?
  • @OneTwoThree:没关系。如果它那么复杂,你可以将复杂的逻辑提取到一个单独的函数中——这相当于你无论如何都会用Function 方法做的事情。使用简单的 for 循环,您仍然可以重复更少的代码。

标签: java guava functional-java


【解决方案1】:

这是一种解决方案。边界检查和所有错误处理都省略了:

public class Reducer
{
    public static <X, Y, Z> List<Z> reduce(List<X> list1, List<Y> list2, Function<X,Y,Z> func)
    {
        List<Z> result = new ArrayList<Z>();
        Iterator<X> i1 = list1.iterator();
        Iterator<Y> i2 = list2.iterator();
        for (int i=0; i<list1.size(); i++)
        {
            result.add(func.apply(i1.next(), i2.next()));
        }
        return result;
    }
}

public interface Function<X,Y,Z> {
    Z apply(X arg1, Y arg2);
}

以及如何使用它

public static void main(String[] args)
{
    Function<Double, Double, Double> f = new Function<Double, Double, Double>() {
        @Override
        public Double apply(Double a1, Double a2) { return a1 * a2; }
    };

    List<Double> d1 = new ArrayList<Double>();
    List<Double> d2 = new ArrayList<Double>();
    List<Double> result = Reducer.reduce(d1, d2, f);
}

【讨论】:

    【解决方案2】:

    主要思想是创建一个方法,它可以一次检索所有列表的所有索引,并将此结果返回到数组或集合中......你不必存储它们,你只需要对它们的引用,您可以将它们作为参数传递给您的方法

    这里有一些创建这种方法的形式,如果你的搜索返回无效结果,你可以创建一个公共值来返回:

    private List<Double> firstList = new ArrayList<Double>();
    private List<Double> secondList = new ArrayList<Double>();
    private List<Double> thirdList = new ArrayList<Double>();
    private static final double OUT_OF_BOUNDS = -1;
    
    // just to initialize the arrays
    private void initializeLists() {
        // dont pay attention to this
        for (double d1 = 0, d2 = 500, d3 = 5000; d1 < 50; d1++, d2++, d3++) {
            firstList.add(d1);
            secondList.add(d2);
            thirdList.add(d3);
        }
    }
    
    // create a method to retrieve data from both lists, and return it in an array or even
    // a new list
    private double[] apply(int index) {
        if (index < firstList.size() && index < secondList.size()) {
            if (index >= 0) {
                return new double[] { firstList.get(index), secondList.get(index) };
            }
        }
        return new double[] { OUT_OF_BOUNDS, OUT_OF_BOUNDS };
    }
    
    // you can pass those lists as parameters
    private double[] apply(int index, List<Double> firstList, List<Double> secondList) {
        if (index < firstList.size() && index < secondList.size()) {
            if (index >= 0) {
                return new double[] { firstList.get(index), secondList.get(index) };
            }
        }
        return new double[] { OUT_OF_BOUNDS, OUT_OF_BOUNDS };
    }
    
    // you can even pass undefined number of lists (var-args)and grab there values at onnce
    private double[] apply(int index, List<Double>... lists) {
    
        int listsSize = lists.length;
    
        if (index >= 0) {
    
            double[] search = new double[listsSize];
    
            for (int listIndex = 0; listIndex < listsSize; listIndex++) {
    
                List<Double> currentList = lists[listIndex];
    
                if (index < currentList.size()) {
                    search[listIndex] = currentList.get(index);
    
                } else {
                    search[listIndex] = OUT_OF_BOUNDS;
                }
    
            }
            return search;
        }
    
        double[] invalidSearch = new double[listsSize];
        for (int i = 0; i < listsSize; i++) {
            invalidSearch[i] = OUT_OF_BOUNDS;
        }
        return invalidSearch;
    
    }
    
    // now the work
    
    public void combineLists() {
        initializeLists();
        double[] search = null;
    
        // search for index Zero in both lists
        search = apply(0);
        System.out.println(Arrays.toString(search));
        // result : [0.0, 500.0]
    
        // search for index One in both list parameters
        search = apply(1, firstList, secondList);
        System.out.println(Arrays.toString(search));
        // result : [1.0, 501.0]
    
        // search for index Two in var-args list parameters
        search = apply(2, firstList, secondList, thirdList);
        System.out.println(Arrays.toString(search));
        // result : [2.0, 502.0, 5002.0]
    
    
        // search for wrong index
        search = apply(800);
        System.out.println(Arrays.toString(search));
        // result : [-1.0, -1.0]
    
        // search for wrong index
        search = apply(800, firstList, secondList);
        System.out.println(Arrays.toString(search));
        // result : [-1.0, -1.0]
    
    
        // search for wrong index
        search = apply(800, firstList, secondList, thirdList);
        System.out.println(Arrays.toString(search));
        // result : [-1.0, -1.0,-1.0]
    
    }
    

    【讨论】:

    • 示例是双精度型,但您可以将双精度型替换为运行时声明的通用类型
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-11
    • 2013-09-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-29
    相关资源
    最近更新 更多