2011-05-18 92 views
2

这个程序是功课。我们已经完成了它,并且很好去。我想知道是否有更简化的写这个程序的方式?该程序被称为Interleave,它所做的是将两个ArrayLists组合起来,以便第一个ArrayList中的每个其他元素都来自第二个ArrayList。听起来很简单,就是我们使用迭代器来添加必要的元素。但代码是BLOCKY。在我看来,必须有更好的方式来写这个,对吧?提前致谢。一个更有效的方法来编写这个程序

import java.util.*; 

public class Interleave 
{ 

public static void main(String[] args) 
{ 

    ArrayList<Integer> a1 = new ArrayList<Integer>(); 
    Collections.addAll(a1, 10, 20, 30); 

    ArrayList<Integer> a2 = new ArrayList<Integer>(); 
    Collections.addAll(a2, 4, 5, 6, 7, 8, 9); 

    System.out.println(a1); 
    System.out.println(a2); 

    System.out.println(interleave(a1, a2)); 

    ArrayList<String> list = new ArrayList<String>(); 
    String[] words = 
    { "how", "are", "you?" }; 

    for (String s : words) 
    { 
     list.add(s); 
    } 

} 

public static ArrayList<Integer> interleave(ArrayList<Integer> a1, 
     ArrayList<Integer> a2) 
{ 
    Iterator<Integer> it = a2.iterator(); 
    int i = 1; 
    while (it.hasNext()) 
    { 
     int val = it.next(); 
     if (a1.size() >= i) 
     { 
      a1.add(i, val); 
     } else 
     { 
      a1.add(val); 
     } 
     i += 2; 
    } 
    return a1; 

} 

}

+5

的Java,作为一种语言,是相当冗长和 “块状”。习惯它。 ;-) – Santa 2011-05-18 18:31:26

+0

@Santa,好吧,至少他的项目不涉及乐高积木,那会变得混乱。也许甚至'块';) – FreeSnow 2011-05-18 18:32:59

+0

你可以用一个for each-loop替换Iterator-while循环,这将为你节省一条高高的线!;) – Jacob 2011-05-18 18:34:17

回答

1

效率比代码看起来更重要。每次在索引i处添加元素时,该索引之后的每个元素都需要由ArrayList向上移动一个索引,因为它使用数组作为其基础数据结构。如果使用避免这个问题的LinkedList,或者如果您创建了第三个数组(第一个数组+第二个数组),并将这些元素添加到该数组中,则此代码效率会更高。再次,你还必须考虑空间,所以制作另一个阵列会增加空间需求。

即使您坚持使用您当前的方法,您应该在添加所有元素之前增加数组的容量。这样,数组的容量已经足够大,可以添加另一个数组中的所有元素,并且不会(可能)需要多次增加。

希望有所帮助。

编辑:

你也可以重新配置阵列提前使得每个第二名已经是空的,这将节省您从我前面描述的阵列转移问题。

+1

效率远不如代码的外观重要。干净的代码不太可能是错误的代码,并且更容易维护。如果你的代码没有足够的效率去完成它的工作,那么对它进行分析并修复重要的部分。 [过早优化是万恶之源。](http://en.wikiquote.org/wiki/Donald_Knuth) – nmichaels 2011-05-18 18:43:57

+0

@nmichaels - 你滥用早熟优化报价。每种情况都有所不同,因此有自己的一套准则。此外,我们任何人都不可能说出什么是“足够有效地完成工作”,因为这是一次学校练习,而且OP没有详细讨论要求。因此,我们只是不提全面更好的解决方案。 – KyleM 2011-05-18 20:25:50

+0

@nmichaels - 我还应该补充一点,过早的优化不是使用糟糕的编程习惯的借口,这正是你所倡导的。在可能的情况下,程序员应该明智地选择数据结构,并且应该进行编码,使其代码具有可读性,可维护性和高效性。这些事情应该根据情况来平衡;过早优化是无关紧要的。 – KyleM 2011-05-18 20:28:08

0

现在,你interleave函数假定一个具体列表实现(ArrayList)和特定类型,它必须包含(Integer)。您可以通过使用泛型概括此功能:

public static <T> List<T> interleave(List<T> first, List<T> second) 
{ 
    Iterator<T> it = second.iterator(); 
    int i = 1; 
    while (it.hasNext()) { 
     T val = it.next(); 
     if (first.size() >= i) 
      first.add(i, val); 
     else 
      first.add(val); 
     i += 2; 
    } 

    return first; 
} 
+0

虽然这仍然强制两个列表包含相同的类型。 – Santa 2011-05-18 18:43:06

2
public static ArrayList<Integer> interleave(ArrayList<Integer> a1, ArrayList<Integer> a2) 
{ 
    Iterator<Integer> it1 = a1.iterator(); 
    Iterator<Integer> it2 = a2.iterator(); 
    ArrayList<Integer> output = new ArrayList<Integer>(); 

    while (it1.hasNext() || it2.hasNext()) 
    { 
     if (it1.hasNext()) { output.add(it1.next()); } 
     if (it2.hasNext()) { output.add(it2.next()); } 
    } 

    return output;  
} 
+0

while条件应该是'||'而不是'&&'以允许不同的长度列表。 – WhiteFang34 2011-05-18 18:52:23

+0

啊,是的。感谢您的支持。 – Lucas 2011-05-18 19:12:10

+0

+1。简洁易读 – patros 2011-05-18 19:22:24

0

我不认为你可以减少代码量很大。它可能无法做得太快。但是,我会提出一些其他改进建议:

  1. 如果您要返回另一个对象,那么对您传入的对象进行变异不是一个好习惯。
  2. 你可以只使用List代替ArrayList所以任何类型的List可以传递。
  3. 你可以使用泛型不能使其具体到Integer列表。

这些组合会产生这样的:

public static <T> List<T> interleave(List<T> a1, List<T> a2) { 
    List<T> list = new ArrayList<T>(a1.size() + a2.size()); 
    Iterator<T> it1 = a1.iterator(); 
    Iterator<T> it2 = a2.iterator(); 

    while (it1.hasNext() || it2.hasNext()) { 
     if (it1.hasNext()) { 
      list.add(it1.next()); 
     } 
     if (it2.hasNext()) { 
      list.add(it2.next()); 
     } 
    } 

    return list; 
} 
+0

好点,但因为它是作业,我将不得不留在项目的规则。 – kreeSeeker 2011-05-19 04:53:46

+0

@ kreeSeeker它可以做得更快,正如我在我的文章中所述。随着元素数量的增加,只需使用LinkedList就可以提高速度。 – KyleM 2011-05-19 13:01:44

相关问题