2011-05-01 73 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.