2011-05-18 94 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

相關問題