Reputation: 1479
My goal is to generate iterative alphabetical/digit string with fixed length, for instance:
aaaaaa
aaaaab
aaaaac
...
aaaaa9
aaaaba
...
999999
It can be easily implemented with nested for loops, like code below:
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]);
}
}
}
}
}
}
}
But it would be good to know how it can be refactored to have for instance possibility to run such code in multiply threads or even some library already exist in order to generate such number.
Any help would be much appreciated.
Upvotes: 1
Views: 227
Reputation:
If you want to get all permutations of 35 chars in at six places I believe that you'll get StackOverflowException because that will be a list with 1'838'265'625 entries with at least 12 bytes each which is 20GB of memory.
Secondly use char array because ints have 4 bytes while char is only 2 (unicode).
At last in concatenations int will outbox to Integer and try to cast to char and I think that you'll get ASCII representation of that int (eg. 1 is "start of heading", a non-printing character)
If u want bounded random generator of words of fixed length then you can use
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();
}
Upvotes: 0
Reputation: 140309
You are generating 35^6=1838265625 values; so you can rewrite it using a single for loop:
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]);
}
So, to rewrite in multiple threads, just divide up the range [0..1838265625)
between your threads, so each thread runs a for loop for a portion of that range, e.g. thread 1 does [0..1_000_000)
, thread 2 does [1_000_000..2_000_000)
etc.
You might find it easier to use a ForkJoinPool
to manage the splitting and joining of the ranges, rather than attempting to do it by hand.
Of course, I'm still thinking in pre-Java 8 terms. You can also do it with streams (as suggested by 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);
Upvotes: 8
Reputation: 123
I don't have 50 points to comment, so posting as an answer.
Why the need for so much nested loops? 2 loops would have been sufficient. Calculate the length of the array, store it in length
Like
for (i=0;i<length;i++)
{
for(i=0;i<6;i++)
{
//what to do
}
}
Upvotes: 1
Reputation: 140427
I think your code could be transformed into a solution using java8 streams. And then you could simply go from a stream() based solution to parallelStream() solution.
The downside is that streams only work with reference types / collections; so you might loose performance by not using the raw char arrays.
Upvotes: 0