I am trying to generate random array of integers using new Stream API in Java 8. But I haven't understood this API clearly yet. So I need help. Here is my code.
Random random = new Random();
IntStream intStream = random.ints(low, high);
int[] array = intStream.limit(limit) // Limit amount of elements
.boxed() // cast to Integer
.toArray();
But this code returns array of objects. What is wrong with it?
If you want primitive int values, do not call IntStream::boxed as that produces Integer objects by boxing.
Simply use Random::ints which returns an IntStream:
int[] array = new Random().ints(size, lowBound, highBound).toArray();
To generate random numbers from range 0 to 350, limiting the result to 10, and collect as a List. Later it could be typecasted.
However, There are no guarantees on the type, mutability, serializability, or thread-safety of the List returned.
List<Object> numbers = new Random().ints(0,350).limit(10).boxed().collect(Collectors.toList());
and to get thearray of int use
int[] numbers = new Random().ints(0,350).limit(10).toArray();
There's no reason to boxed(). Just receive the Stream as an int[].
int[] array = intStream.limit(limit).toArray();
tl;dr
ThreadLocalRandom // A random number generator isolated to the current thread.
.current() // Returns the current thread's `ThreadLocalRandom` object.
.ints( low , high ) // Pass the "origin" (inclusive) and "bound" (exclusive).
.limit( 100 ) // How many elements (integers) do you want in your stream?
.toArray() // Convert the stream of `int` values into an array `int[]`.
ThreadLocalRandom
You can do it using ThreadLocalRandom.
The ints method generates an IntStream within your specified bounds. Note the the low is inclusive while the high is exclusive. If you want to include your high number, just add one while calling the ints method.
int[] randInts = ThreadLocalRandom.current().ints( low , high ).limit(100).toArray();
See this code run live at IdeOne.com.
Related
I'm learning java and was told arrays are implemented as objects. But they show two different codes without diving into details.
First they ask us to use arrays like this, but the downside is to manually add the values:
int nums[] = new int[10];
nums[0] = 99;
nums[1] = -622;
.
.
.
Then they use this in some programs saying new is not needed because Java automatically does stuff:
int nums[] = {99, - 10, 100123, 18, - 972 ......}
If the second code is shorter and allows me to use arrays straightaway whats the point of the first code if they do the same thing but the first one require more code to input value by hand.
Let's say you were initializing an array of 1 million values, would you use the second method? No, because you would have a huge java file.
The first method is essentially allocating space:
int[] array = new int[1000000];
Creates 1 million spaces in memory with default value 0. Now if you want to initialize them, you may use a loop:
for (int i = 0; i < array.length; i++) {
array[i] = i;
}
If you wanted an array of 10 million values, you only change one number:
// Just add a 0 to 1000000
int[] array = new int[10000000]
Now, if the size of your array changes, you don't have to change the loop. But if you used the second method and wanted an array of 10 million values, you would have to add 9 million values, and 9 million commas to your java file - not scalable.
int[] array = {1, 2, 3, 4, ... 1000000};
The second method is not "scalable." It only works for small arrays where you can confidently assume that the default values of that array won't change. Otherwise, it makes A LOT more sense to use the first (more common) method.
//This is one way of declaring and initializing an array with a pre-defined size first
int nums[] = new int[10];
//This is initializing the array with a value at index 0
nums[0] = 99;
//This is initializing the array with a value at index 1 and likewise allocating rest of array index values
nums[1] = -622;
//This is another way of declaring and initializing an array directly with pre-defined values. Here if you see instead of declaring array size first, directly the values are initialized for it
int nums[] = {99, - 10, 100123, 18, - 972 ......}
It depends on the way you prefer to use the arrays, but you must remember that whenever you use "new" keyword, there is a new space or resource created every time in memory.
When you don't know the items of array at the time of array declaration, then prefer method-1,
and,
when you know the all the values of array at the time of array declaration, then go for method-2
Imagine you want to generate a series of random integers at runtime and want to store in the array:
int[] array = new int[1000000];
Random r = new Random();
for (int i = 0; i < array.length; i++)
array[i] = r.nextInt();
I am trying to make a program to apply an operation between all values in an array or string, however the operation is a bitwise ^ operation between all the elements. Is there anything that can do this? Between my knowledge of lists and arrays I don't even know where to start.
EX:
int[] n = {0,1,2,3,4,6}
// program that can do the operation for 0^1^2^3^4^6
You can't do that with arrays but you can achieve what you wanna do with the list using streams;
List<Integer> l = Arrays.asList(1,2,3,4,6);
int res = l.stream().reduce(0, (m,k) -> m +k);
I have just discovered the new Java 8 stream capabilities. Coming from Python, I was wondering if there was now a neat way to do operations on arrays like summing, multiplying two arrays in a "one line pythonic" way ?
Thanks
There are new methods added to java.util.Arrays to convert an array into a Java 8 stream which can then be used for summing etc.
int sum = Arrays.stream(myIntArray).sum();
Multiplying two arrays is a little more difficult because I can't think of a way to get the value AND the index at the same time as a Stream operation. This means you probably have to stream over the indexes of the array.
//in this example a[] and b[] are same length
int[] a = ...
int[] b = ...
int[] result = new int[a.length];
IntStream.range(0, a.length).forEach(i -> result[i] = a[i] * b[i]);
Commenter #Holger points out you can use the map method instead of forEach like this:
int[] result = IntStream.range(0, a.length).map(i -> a[i] * b[i]).toArray();
You can turn an array into a stream by using Arrays.stream():
int[] ns = new int[] {1,2,3,4,5};
Arrays.stream(ns);
Once you've got your stream, you can use any of the methods described in the documentation, like sum() or whatever. You can map or filter like in Python by calling the relevant stream methods with a Lambda function:
Arrays.stream(ns).map(n -> n * 2);
Arrays.stream(ns).filter(n -> n % 4 == 0);
Once you're done modifying your stream, you then call toArray() to convert it back into an array to use elsewhere:
int[] ns = new int[] {1,2,3,4,5};
int[] ms = Arrays.stream(ns).map(n -> n * 2).filter(n -> n % 4 == 0).toArray();
Be careful if you have to deal with large numbers.
int[] arr = new int[]{Integer.MIN_VALUE, Integer.MIN_VALUE};
long sum = Arrays.stream(arr).sum(); // Wrong: sum == 0
The sum above is not 2 * Integer.MIN_VALUE.
You need to do this in this case.
long sum = Arrays.stream(arr).mapToLong(Long::valueOf).sum(); // Correct
Please note that Arrays.stream(arr) create a LongStream (or IntStream, ...) instead of Stream so the map function cannot be used to modify the type. This is why .mapToLong, mapToObject, ... functions are provided.
Take a look at why-cant-i-map-integers-to-strings-when-streaming-from-an-array
I have created a method to randomize the list:
public <T> List<T> randomize(List<T> list) {
LinkedList<T> randomizedList = new LinkedList<>();
Random random = new Random(list.size());
for (int i = random.nextInt(); i < list.size(); i++) {
randomizedList.add(list.get(i));
}
return randomizedList;
}
The list that I am passing to this method contains for e.g. five elements. When I am creating Random random = new Random(list.size()); I expect so when I call random.nextInt() what it will return me the random integer which will be an index of the list element.
But when I call random.nextInt(); instead of returning the number from the interval [0, 4] (which I expect to be returned) it returns me the value of for e.g.: -349120689. Which gives me an java.lang.IndexOutOfBoundsException: Index: -349120689, Size: 5.
Why is this happening and how to solve this?
new Random(list.size()); this sets the seed of the Random number generator to list.size(); I suggest changing to new Random() (which will give you a seed based on the current time of the system). Preferably though, you'd want to reuse the same Random object at all times.
random.nextInt(); here is where you'd want to put random.nextInt(list.size()); which will give you a number from 0 to list.size() - 1.
Even with the above changes, your code would just give you a sublist of the list starting at a random index and going until the end. Use Collections.shuffle(list) instead.
To do a real shuffling, you would need to "remember" which elements
you have inserted or not. In pseudo-code, you could do the
following:
Copy the original list to a new one, let's call it "orig"
Create a new, empty, list, let's call it "result"
As long as the orig list has elements, get an element at random index and add it to the result list. Remove the chosen element from orig list.
Return result list.
I expect so when I call random.nextInt() what it will return me the random integer which will be an index of the list element.
You've misunderstood the purpose of the Random(long) constructor. The purpose of that constructor is to specify a seed for the list. You don't want to do this - it would mean that every collection of size 5 is always shuffled the same way.
You specify the range on each call to nextInt. So if you want a random number between 0 (inclusive) and max (exclusive) you just use:
int value = random.nextInt(max);
However, it would be much better just to use Collections.shuffle instead of writing your own code to do this - assuming you really want a shuffle (which isn't what your current approach would give you anyway - even after fixing the nextInt call, you'd end up
with basically a sublist, because nextInt() is only called once. So if the first call to nextInt() returns 2 (in a list of 5) you'd end up returning a new list containing the final 3 elements. I strongly suspect that's not what you were trying to do.
As a side-note, when you want to know why an API isn't behaving the way you expect it to, read the documentation. The documentation of the Random(long) constructor and Random.nextInt() are pretty clearly not the behaviour you were expecting.
use this
public <T> List<T> randomize(List<T> list) {
LinkedList<T> randomizedList = new LinkedList<>();
Random random = new Random();
for (int i = random.nextInt(list.size()); i < list.size(); i++) {
randomizedList.add(list.get(i));
}
return randomizedList;
}
The argument to the Random constructor is a random seed, not the maximum of what it returns.
Pass the maximum number to nextInt() instead.
You're confusing the argument to nextInt(n) (upper bound for the randomization) with the argument to the constructor (random seed). You shoudl use nextInt(list.size), and probably, initialize the Random object using new Random().
Today i did learn two ways of accessing the array, i would like to know the various ways of accessing an array element and the best practice of it. I am a student learning algorithm.
int [] arr;
long [] arr;
Advantages of long datatype declaration over int.
class ArrayApp{
public static void main(final String[] args){
long [] arr;
arr= new long[2];
int i;
arr[0]=112;
arr[1]=111;
**// Way one**
for(long l:arr)
{
System.out.println(l);
}
**// Way Two**
for(i=0;i<arr.length;i++) {
System.out.println(arr[i]);
}
}
}
There is no real difference between the ways here. Way one is just a syntax sugar for not to create an additional interation value.
The first way is preferable as it doesn't require an int i; variable and requires less printing. The second should be used when you don't want to iterate through the all array, but just a part of it.
There is no other ways to access the elements of array in java.
We've one declaration of an array:
long[] values = new long[100];
This creates an array for 100 long type values. Each value has an index (position) inside the array, the first index (an int value!) is 0, the last one is 99.
The traditional for loop increments an integer value to generate index position numbers. Those int values are used to access the long values of the array:
for (int index=0; index < values.length; index++) { // index is int
long value = values[index]; // value is long
// do something with value
}
The "enhanced" for loop simply hides this index and gives access to the long values with less code:
for (long value:values) {
// do something with value
}
That's all. If you don't need the index variable in your code, just use the enhanced for loop (second version in my answer)
The first way
for(long l:arr)
{
System.out.println(l);
}
The java runtime will autobox the l to a Long, as iterating this way requires that the class implement the Iterable interface. This way, also does not provide the current index of the array.
The second way
for(i=0;i<arr.length;i++) {
System.out.println(arr[i]);
}
Requires no casts to Long and you also have access to the current index. You also however have to be careful about iterating past the end of the array or accessing array elements below 0.
An int is shorter as a long. You can make an array of any object or primitive type. int[], Integer[], CustomClass[], whatever.
From java documentation:
int: The int data type is a 32-bit
signed two's complement integer. It
has a minimum value of -2,147,483,648
and a maximum value of 2,147,483,647
(inclusive). For integral values, this
data type is generally the default
choice unless there is a reason (like
the above) to choose something else.
This data type will most likely be
large enough for the numbers your
program will use, but if you need a
wider range of values, use long
instead.
long: The long data type is a 64-bit
signed two's complement integer. It
has a minimum value of
-9,223,372,036,854,775,808 and a maximum value of
9,223,372,036,854,775,807 (inclusive).
Use this data type when you need a
range of values wider than those
provided by int.