2011-05-01 77 views
1

我收到了一些代碼,我試圖把它放在一個更好的格式通過其冷凝:如何濃縮此代碼?

ArrayList<Integer> a = new ArrayList<Integer>(); 
ArrayList<Integer> c = new ArrayList<Integer>(); 

for(int i = 0; i < 10; i++) { 

    int nextInt = rand.nextInt(); 

    while((a.contains(nextInt) ? 1:0) + ((nextInt < 0) ? 1:0) + 
             ((nextInt > 1000) ? 1:0) >= 1){ 
     nextInt = rand.nextInt(); 
    } 

    a.add(nextInt); 

    nextInt = rand.nextInt(); 

    while(((c.contains(nextInt))?1:0) + ((nextInt < 0)?1:0) + 
             ((nextInt > 1000)?1:0) >= 1) { 
     nextInt = rand.nextInt();    
    } 

    c.add(nextInt); 
} 

在while循環有完全相同的代碼,但我不知道我是否合併的隨機性會丟失它。然而,這種情況對我來說似乎很奇怪,任何人都可以解釋它?你會如何壓縮這段代碼?

+0

「通過凝結使其更好的形式」 - 這根本不是一個好方法。 「凝結」的代碼通常不會使其更快(只會更難閱讀和理解) – Mat 2011-05-01 18:01:13

+0

將它變成一種方法並使用該方法而不是多次寫入它? – adorablepuppy 2011-05-01 18:03:14

+1

這段代碼應該做什麼?用這種奇怪的邏輯(挑選隨機數然後根據數值進行切換),將它封裝到具有合理名稱的方法中很重要。另一件突出的事情是,當你在循環中迭代時,你一直調用'Array#contains',給它一個O(n^2)運行時。但在優化之前,請考慮你想要完成的是什麼,因爲可能有更好的方法。 – 2011-05-01 18:10:39

回答

1

您的while循環基本上確保隨機數在0和1000之間(包括兩者),並且它以前不在列表中。您可以通過調用java.util.Random.nextInt(int n)方法來優化範圍限制。如果您的應用程序允許您使用Set而不是List,則您甚至不需要檢查contains

這裏,如果您使用的是List你如何能凝聚代碼:

public void addUniqueRandom(List<Integer> list) { 
    int nextInt; 
    do { 
     nextInt = rand.nextInt(1001); 
    } while(list.contains(nextInt)); 

    list.add(nextInt); 
} 

ArrayList<Integer> a = new ArrayList<Integer>(); 

ArrayList<Integer> c = new ArrayList<Integer>(); 

for(int i = 0; i < 10; i++) { 
    addUniqueRandom(a); 
    addUniqueRandom(c); 
} 

使用Set S,您需要輸入要小得多:

Set<Integer> a = new HashSet<Integer>(); 

Set<Integer> c = new HashSet<Integer>(); 

for(int i = 0; i < 10; i++) { 
    while (!a.add(rand.nextInt(1001))) // keep trying until we successfully add 
     ; 
    while (!c.add(rand.nextInt(1001))) 
     ; 
} 
1

(a.contains(nextInt) ? 1:0) + ((nextInt < 0) ? 1:0) + ((nextInt > 1000) ? 1:0) >= 1 - >a.contains(nextInt) || nextInt < 0 || nextInt > 1000

1
ArrayList<Integer> a = new ArrayList<Integer>(); 
ArrayList<Integer> c = new ArrayList<Integer>(); 

public void function(ArrayList<Integer> array){ 
    int nextInt = rand.nextInt(); 

    while((array.contains(nextInt) ? 1:0) || ((nextInt < 0) ? 1:0) || 
             ((nextInt > 1000) ? 1:0) >= 1){ 
     nextInt = rand.nextInt(); 
    } 

    array.add(nextInt); 


} 

for(int i = 0; i < 10; i++) { 
    function(a); 
    function(c); 
} 

號的隨機性會丟失。

+0

我同意你的意見; while條件只有一點改進:while(array.container(nextInt)|| nextInt <0 || nextInt> 1000)將更具可讀性。 – 2011-05-01 18:09:26

+0

此外,由於列表大小是固定的,我建議**用'int []'替換**'ArrayList '。 – 2011-05-01 18:14:57

2

的同時,條件是讓我想起了C風格的條件,其中假爲0,真正的是除了0。但是,Java有明確的布爾值的東西,所以它是使用像這樣的條件更有意義:

a.contains(nextInt) || (nextInt < 0) || (nextInt > 1000) 

該代碼被放入while循環中,因爲代碼顯然需要生成一個從0到1000(含)的唯一數字列表。如果它違反了「存儲」的三個條件中的任何一個,那麼我們需要生成一個新的隨機數然後重試。如果它違反了第一個條件,那麼它意味着該數字不是唯一的,並且如果它違反後兩個條件中的任一個,則意味着它不在指定範圍內。

我可能會把這個循環放在一個名爲generateUniqueValueInrange或類似的東西里,列表和邊界作爲參數。另外,我猜rand是一個java.util.Random對象。請注意,Random有一個nextInt(int n)方法,該方法將爲您生成一個範圍內的數字,以便您不必一直生成新數字,直到它們碰巧處於所需範圍內。請參閱http://download.oracle.com/javase/6/docs/api/java/util/Random.html#nextInt%28int%29

另請注意,您正試圖生成兩個從0到1000的10個唯一數字的列表。因此,您可能會考慮採用更直接的方法來完成此操作。我個人基本上使用了這裏的方法來做類似的任務,但是「直到隨機性適用於我」的方法很容易出錯,因爲如果條件不可行,很容易陷入無限循環。

1

它看起來像你希望兩個列表中包含唯一的隨機數集。這是我會做:

List<Integer> a = getRandomUniqueList(10, 0, 1000); 
List<Integer> b = getRandomUniqueList(10, 0, 1000); 

public List<Integer> getRandomUniqueList(int count, int min, int max) { 
    Random rand = new Random(); 
    Set<Integer> set = new HashSet<Integer>(); 
    for (int i = 0; i < count; i++) { 
     while (!set.add(min + rand.nextInt(max - min + 1))) { 
     } 
    } 
    return new ArrayList<Integer>(set); 
} 

Random類已經有限制範圍的方法。將值初始化爲Set可以輕鬆地跳過重複項。重用代碼對隨機性沒有影響。也不會改變這種方法,但如果您要使用相同的種子,您將得到不同的隨機數。如果您真的想要想要更好的隨機性,那麼請使用SecureRandomMersenne Twister來代替。

1

使用Set(對於沒有重複的集合更有意義),只需要一個循環。

public static Set<Integer> generate(int count, int maxValue) { 
    Set<Integer> ints = new HashSet<Integer>(); 
    while(ints.size() < count) list.add(rand.nextInt(maxValue+1))); 
    return ints; 
} 

Set<Integer> a = generate(10, 1000); // for a set. 
List<Integer> c = new ArrayList<Integer>(generate(10, 1000)); // for a list.