有没有更优雅的方式来处理Java中的列表? (Python VS Java)

时间:2011-01-11 20:09:06

标签: java python list operators language-design

我喜欢用Python处理列表的方式。它做任何递归解决方案看起来容易和干净。例如,在Python中获取元素的所有排列的典型问题如下所示:

def permutation_recursion(numbers,sol):
    if not numbers:
        print "this is a permutation", sol
    for i in range(len(numbers)):
        permutation_recursion(numbers[:i] + numbers[i+1:], sol + [numbers[i]])

def get_permutations(numbers):
    permutation_recursion(numbers,list())

if __name__ == "__main__":
    get_permutations([1,2,3])

我喜欢通过这样的方式简单地获取修改后的列表的新实例的方式 numbers[:i] + numbers[i+1:]sol + [numbers[i]]

如果我尝试在Java中编写完全相同的代码,它看起来像:

import java.util.ArrayList;
import java.util.Arrays;

class rec {
    static void permutation_recursion(ArrayList<Integer> numbers, ArrayList<Integer> sol) {
       if (numbers.size() == 0)
            System.out.println("permutation="+Arrays.toString(sol.toArray()));
       for(int i=0;i<numbers.size();i++) {
             int n = numbers.get(i);

             ArrayList<Integer> remaining = new ArrayList<Integer>(numbers);
             remaining.remove(i);

             ArrayList<Integer> sol_rec = new ArrayList<Integer>(sol);
             sol_rec.add(n);

             permutation_recursion(remaining,sol_rec);
       }
    }
    static void get_permutation(ArrayList<Integer> numbers) {
        permutation_recursion(numbers,new ArrayList<Integer>());
    }
    public static void main(String args[]) {
        Integer[] numbers = {1,2,3};
        get_permutation(new ArrayList<Integer>(Arrays.asList(numbers)));
    }
}

要创建我需要做的相同递归:

ArrayList<Integer> remaining = new ArrayList<Integer>(numbers);
remaining.remove(i);

ArrayList<Integer> sol_rec = new ArrayList<Integer>(sol);
sol_rec.add(n);

这对于更复杂的解决方案而言非常难看。就像this example

一样

所以我的问题是...... Java API中是否有任何内置运算符或辅助函数可以使这个解决方案更“Pythonic”?

5 个答案:

答案 0 :(得分:8)

没有。

但这就是Martin Odersky创造Scala的原因。他甚至说他对Scala的目标之一就是它是Java世界的Python。 Scala编译为Java字节码,并且可以轻松地与Java编译类进行交互。

如果这不是一个选项,您可以查看Commons Collection Library

答案 1 :(得分:2)

您可以使用列表上的clone()函数来获取它们的浅表副本。这样你就不必自己实例化一个新的对象,但只能使用副本。

ArrayList<Integer> remaining = remaining.clone().remove(i);

除此之外,不,java没有列表的运算符。

答案 2 :(得分:1)

Apache Commons解决了很多这类问题。看看ArrayUtils做切片。由于各种原因,Java没有像脚本语言那样的大量语法糖。

答案 3 :(得分:1)

不同的语言需要不同的风格。尝试在java中完成mylist[:i] + mylist[i+1:]就像使用带螺丝的锤子一样。是的,你可以做到,但它不是很整洁。我相信等价物可能类似于ArrayList temp = new ArrayList(list); temp.remove(index);

我相信以下内容可以完成相同的任务,但是会以稍微不同的方式完成,但不会出现可读性问题。它不是创建新列表,而是修改列表,传递它,并在递归调用返回时将列表返回到先前的状态。

import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;

public class Permutation {

   public static void main(String[] args) {

      List<List<Integer>> result = permutations(
                                       Arrays.asList( 
                                          new Integer[] {1,2,3}));

      for (List<Integer> permutation : result) {
         System.out.println(permutation);  
      }
   }


   public static <T> List<List<T>> permutations(List<T> input) {
      List<List<T>> out = new ArrayList<List<T>>();
      permutationsSlave(input, new ArrayList<T>(), out);
      return out;
   }

   public static <T> void permutationsSlave(List<T> input, 
            ArrayList<T> permutation, List<List<T>> result) {

      if (input.size() == chosen.size()) {
         result.add(new ArrayList<T>(permutation));
         return;
      }

      for (T obj : input) {
         if (!permutation.contains(obj)) {
            permutation.add(obj);
            permutationsSlave(input, permutation, result);
            permutation.remove(permutation.size()-1);
         }
      } 

   }
}

python方式可能看起来更简单,更清晰,但看起来干净的能力通常会隐藏这样一个事实:解决方案效率非常低(对于每个级别的递归,它会创建5个新列表)。

但是我自己的解决方案也不是非常有效 - 它不是创建多个新对象而是执行冗余比较(尽管可以通过使用累加器来缓解一些)。

答案 4 :(得分:0)

您好 1你可以使用堆栈,这将更方便。

2 for循环可以这样写: for(Number n:numbers)