生成具有固定长度的字母/数字字符串

时间:2016-10-19 06:53:44

标签: java

我的目标是生成具有固定长度的迭代字母/数字字符串,例如:

aaaaaa
aaaaab
aaaaac
...
aaaaa9
aaaaba
...
999999

可以使用嵌套for循环轻松实现,如下面的代码:

   public static void main(String[] strings) {
        Object[] array = new Object[]{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
                'y', 'z', 0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
        List<String> list = Lists.newArrayList();
        int a, b, c, d, e, f;
        for (a = 0; a < 35; a++) {
            for (b = 0; b < 35; b++) {
                for (c = 0; c < 35; c++) {
                    for (d = 0; d < 35; d++) {
                        for (e = 0; e < 35; e++) {
                            for (f = 0; f < 35; f++) {
                                list.add("" + array[a] + array[b] + array[c] + array[d] + array[e] + array[f]);
                            }
                        }
                    }
                }
            }
        }
    }

但最好知道如何重构它可以在多个线程中运行这样的代码,或者甚至已经存在一些库以生成这样的数字。

非常感谢任何帮助。

4 个答案:

答案 0 :(得分:8)

您正在生成35 ^ 6 = 1838265625个值;所以你可以用一个for循环重写它:

for (int i = 0; i < 1838265625; ++i) {
  int ii = i;
  int f = ii % 35; ii /= 35;
  int e = ii % 35; ii /= 35;
  int d = ii % 35; ii /= 35;
  // ...
  int a = ii % 35;

  list.add("" + array[a] + array[b] + array[c] + array[d] + array[e] + array[f]);
}

因此,要在多个线程中重写,只需在线程之间划分范围[0..1838265625),这样每个线程就会为该范围的一部分运行for循环,例如:线程1执行[0..1_000_000),线程2执行[1_000_000..2_000_000)等。

您可能会发现使用ForkJoinPool来管理范围的拆分和连接更容易,而不是尝试手动执行。

当然,我仍然在考虑Java 8之前的术语。您也可以使用流(如GhostCat建议):

IntStream.range(0, 1838265625).parallelStream()
    .map(i -> {
        int ii = i;
        int f = ii % 35; ii /= 35;
        int e = ii % 35; ii /= 35;
        int d = ii % 35; ii /= 35;
        // ...
        int a = ii % 35;
        return "" + array[a] + array[b] + array[c] + array[d] + array[e] + array[f]; })
    .collect(someCollector);

答案 1 :(得分:1)

我没有50分可以评论,所以发帖作为答案。

为什么需要这么多嵌套循环? 2个循环就足够了。计算数组的长度,将其存储在length

for (i=0;i<length;i++)
 {
  for(i=0;i<6;i++)
   {
       //what to do
   }
}

答案 2 :(得分:0)

我认为您的代码可以使用java8流转换为解决方案。然后你可以简单地从基于stream()的解决方案转到parallelStream()解决方案。

缺点是流只能使用引用类型/集合;因此,如果不使用原始字符数组,可能会导致性能下降。

答案 3 :(得分:0)

  • 如果你想在六个地方获得35个字符的所有排列,我相信你会得到StackOverflowException,因为那将是一个包含1'838'265'625个条目的列表,每个条目至少12个字节是20GB的内存。

  • 其次使用char数组,因为int有4个字节而char只有2个(unicode)。

  • 最后在连接中,int将outbox转换为Integer并尝试转换为char,我认为你将获得该int的ASCII表示(例如,1是“标题的开头”,非打印字符)

  • 如果你想要固定长度字的有界随机生成器,那么你可以使用

private static final String[] array = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x",
            "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};

public List<String> randomWords(int numOfWords, int lengthOfWord){
     List<String> list = new ArrayList<>();
     for(int i = 0; i < numberOfWords; i++)
         list.add(randomWord(lengthOfWord));

     return list;
}

private String randomWord(int lengthOfWord){
    Random rand = new Random(); 
    StringBuilder sb = new StringBuilder();
    for(int i = 0; i < lengthOfWord; i++){
        sb.append(array[rand.nextInt(35)]);
    }
    return sb.toString();
}