You could use Stream#generate with limit:
Stream.generate(MyClass::new).limit(10);
Answer from Alex - GlassEditor.com on Stack OverflowYou could use Stream#generate with limit:
Stream.generate(MyClass::new).limit(10);
If you know n in advance, I think it's more idiomatic to use one of the stream sources that creates a stream that is known to have exactly n elements. Despite the appearances, using limit(10) doesn't necessarily result in a SIZED stream with exactly 10 elements -- it might have fewer. Having a SIZED stream improves splitting in the case of parallel execution.
As Sotirios Delimanolis noted in a comment, you could do something like this:
List<MyClass> list = IntStream.range(0, n)
.mapToObj(i -> new MyClass())
.collect(toList());
An alternative is this, though it's not clear to me it's any better:
List<MyClass> list2 = Collections.nCopies(10, null).stream()
.map(o -> new MyClass())
.collect(toList());
You could also do this:
List<MyClass> list = Arrays.asList(new MyClass[10]);
list.replaceAll(o -> new MyClass());
But this results in a fixed-size, though mutable, list.
Videos
There are multiple ways you could change your snippet here to use Java-8 Streams. Here an overview of a few straight out of my head.
List<IDWrapper> list = IntStream.range( 0, 20 ).mapToObj( IDWrapper::new ).collect( Collectors.toList() );
List<String> details = list.stream().map( IDWrapper::getId ).map( this::getDetails ).collect( Collectors.toList() );
List<String> details2 = list.stream().map( item -> item.getId() ).map( id -> getDetails( id ) ).collect( Collectors.toList() );
List<String> details3 = list.stream().map( item -> getDetails( item.getId() ) ).collect( Collectors.toList() );
Let's break them down and explain their differences a bite more.
1.
List<String> details = list.stream().map( IDWrapper::getId ).map( this::getDetails ).collect( Collectors.toList() );
This one uses MethodReferences to pass the desired functions down the Stream#map(Function) method. It can be read as 'map the items, which are IDWrapper-Objects and do it by calling IDWrapper#getId() on every object and put the resulting items (integer values in this case) back into the stream'. Afterwards another call to Stream#map(Function) is done but this time the object to operate on is 'this' (my dummy class i created for the example) and call the #getDetails(int) method on this class.
2.
List<String> details2 = list.stream().map( item -> item.getId() ).map( id -> getDetails( id ) ).collect( Collectors.toList() );
This one is quite simply equal to 1. but using usual lambda expression to achieve the same.
3.
List<String> details3 = list.stream().map( item -> getDetails( item.getId() ) ).collect( Collectors.toList() );
In this case we're defining the function as a lamda and simply chaining the method class.
As mentioned before there are lots of other possibilities, but here are an education few. Hope I could help you understanding streams a little bit better.
Something like:
Map<String,Integer> m =
list.stream()
.collect(Collectors.toMap(e -> e.getUser, // key extractor
e -> getDetail(e.getId()).getBody().getData() // value extractor
)
);
----EDIT----
Ho ho... This is exactly Holger's comment. Give credit where credit is due.
IntStream.range(0, 1000)
/* .parallel() */
.filter(i -> i+1 % 100 == 0)
.peek(i -> System.out.println("Test number " + i + " started."))
/* other operations on the stream including a terminal one */;
If the test is running on each iteration regardless of the condition (take the filter out):
IntStream.range(0, 1000)
.peek(i -> {
if (i + 1 % 100 == 0) {
System.out.println("Test number " + i + " started.");
}
}).forEach(i -> {/* the test */});
Another approach (if you want to iterate over an index with a predefined step, as @Tunaki mentioned) is:
IntStream.iterate(0, i -> i + 100)
.limit(1000 / 100)
.forEach(i -> { /* the test */ });
There is an awesome overloaded method Stream.iterate(seed, condition, unaryOperator) in JDK 9 which perfectly fits your situation and is designed to make a stream finite and might replace a plain for:
Stream<Integer> stream = Stream.iterate(0, i -> i < 1000, i -> i + 100);
You can use IntStream as shown below and explained in the comments:
(1) Iterate IntStream range from 1 to 1000
(2) Convert to parallel stream
(3) Apply Predicate condition to allow integers with (i+1)%100 == 0
(4) Now convert the integer to a string "Test number "+i+" started."
(5) Output to console
IntStream.range(1, 1000). //iterates 1 to 1000
parallel().//converts to parallel stream
filter( i -> ((i+1)%100 == 0)). //filters numbers & allows like 99, 199, etc..)
mapToObj((int i) -> "Test number "+i+" started.").//maps integer to String
forEach(System.out::println);//prints to the console
For this specific example, you could do:
IntStream.rangeClosed(1, 8)
.forEach(System.out::println);
If you need a step different from 1, you can use a mapping function, for example, for a step of 2:
IntStream.rangeClosed(1, 8)
.map(i -> 2 * i - 1)
.forEach(System.out::println);
Or build a custom iteration and limit the size of the iteration:
IntStream.iterate(1, i -> i + 2)
.limit(8)
.forEach(System.out::println);
Here's another technique I ran across the other day:
Collections.nCopies(8, 1)
.stream()
.forEach(i -> System.out.println(i));
The Collections.nCopies call creates a List containing n copies of whatever value you provide. In this case it's the boxed Integer value 1. Of course it doesn't actually create a list with n elements; it creates a "virtualized" list that contains only the value and the length, and any call to get within range just returns the value. The nCopies method has been around since the Collections Framework was introduced way back in JDK 1.2. Of course, the ability to create a stream from its result was added in Java SE 8.
Big deal, another way to do the same thing in about the same number of lines.
However, this technique is faster than the IntStream.generate and IntStream.iterate approaches, and surprisingly, it's also faster than the IntStream.range approach.
For iterate and generate the result is perhaps not too surprising. The streams framework (really, the Spliterators for these streams) is built on the assumption that the lambdas will potentially generate different values each time, and that they will generate an unbounded number of results. This makes parallel splitting particularly difficult. The iterate method is also problematic for this case because each call requires the result of the previous one. So the streams using generate and iterate don't do very well for generating repeated constants.
The relatively poor performance of range is surprising. This too is virtualized, so the elements don't actually all exist in memory, and the size is known up front. This should make for a fast and easily parallelizable spliterator. But it surprisingly didn't do very well. Perhaps the reason is that range has to compute a value for each element of the range and then call a function on it. But this function just ignores its input and returns a constant, so I'm surprised this isn't inlined and killed.
The Collections.nCopies technique has to do boxing/unboxing in order to handle the values, since there are no primitive specializations of List. Since the value is the same every time, it's basically boxed once and that box is shared by all n copies. I suspect boxing/unboxing is highly optimized, even intrinsified, and it can be inlined well.
Here's the code:
public static final int LIMIT = 500_000_000;
public static final long VALUE = 3L;
public long range() {
return
LongStream.range(0, LIMIT)
.parallel()
.map(i -> VALUE)
.map(i -> i % 73 % 13)
.sum();
}
public long ncopies() {
return
Collections.nCopies(LIMIT, VALUE)
.parallelStream()
.mapToLong(i -> i)
.map(i -> i % 73 % 13)
.sum();
}
And here are the JMH results: (2.8GHz Core2Duo)
Benchmark Mode Samples Mean Mean error Units
c.s.q.SO18532488.ncopies thrpt 5 7.547 2.904 ops/s
c.s.q.SO18532488.range thrpt 5 0.317 0.064 ops/s
There is a fair amount of variance in the ncopies version, but overall it seems comfortably 20x faster than the range version. (I'd be quite willing to believe that I've done something wrong, though.)
I'm surprised at how well the nCopies technique works. Internally it doesn't do very much special, with the stream of the virtualized list simply being implemented using IntStream.range! I had expected that it would be necessary to create a specialized spliterator to get this to go fast, but it already seems to be pretty good.
You can do it like this:
IntStream.range(0, numbers.length)
.forEach(index -> {
doubleNumbers[index] = numbers[index] * 2;
tripleNumbers[index] = numbers[index] * 3;
});
You can apply the doubling and tripling within the stream:
public static void main(String[] args) {
int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8};
System.out.println("Double Numbers");
Arrays.stream(numbers).map(x -> x * 2).forEach(System.out::println);
System.out.println("Triple Numbers");
Arrays.stream(numbers).map(x -> x * 3).forEach(System.out::println);
}
though technically that's still iterating over the array twice.
As a trick you could instead collect the results in a Map:
Map<Integer, Integer> m = Arrays.stream(numbers)
.boxed()
.collect(Collectors.toMap(
x -> x * 2,
x -> x * 3
));
You can't perform two terminal operations - forEach and collect on the same Stream.
instead, you need to filter the cars list by checking for each car if it has a matching working wheel :
List<Car> filteredCars =
cars.stream()
.filter (
car -> wheels.stream()
.anyMatch(wheel -> wheel.getColor() == car.getColor() &&
wheel.isWorking()))
.collect(Collectors.toList());
The problem is, you're creating the List(s) inside the forEach and forEach returns void. This would be the equivalent of the following for loop:
for (Car car : cars) {
List<Car> filteredCars = new ArrayList<>();
for (Wheel wheel : wheels) {
if (car.getColor() == wheel.getColor() &&
wheel.isWorking() == true ) {
filteredCars.add(car);
break;
}
}
}
return filteredCars; // whoops cannot be accessed (scope) !!!
You could use filter on the cars stream and collect the use collect on the filtered stream to achieve the desired results:
Predicate<Car> carCheck = car -> wheels.stream().anyMatch(wheel -> car.getColor() == wheel.getColor() && wheel.isWorking());
List<Car> filteredCars = cars.stream().filter(carCheck).collect(Collectors.toList());
I would suggest you make a list of all the user ids outside the loop. Just make sure the class Id overrides equals() function.
List<Id> allUsersIds = allUserNodes.stream().map(n -> n.getNodeId()).collect(Collectors.toList());
for (ItemSetNode itemSetNode : itemSetNodeList)
{
Id nodeId = itemSetNode.getNodeId();
if (!allUsersIds.contains(nodeId))
{
isUserMissingNode = true;
break;
}
}
The following code should be equivalent, except that the value of the boolean is reversed so it's false if there are missing nodes.
First all the user node Ids are collected to a TreeSet (if Id implements hashCode() and equals() you should use a HashSet). Then we stream itemSetNodeList to see if all those nodeIds are contained in the set.
TreeSet<Id> all = allUserNodes
.stream()
.map(n -> n.getNodeId())
.collect(Collectors.toCollection(TreeSet::new));
boolean isAllNodes = itemSetNodeList
.stream()
.allMatch(n -> all.contains(n.getNodeId()));
There are many ways to write equivalent (at least to outside eyes) code, this uses a Set to improve the lookup so we don't need to keep iterating the allUserNodes collection constantly.
You want to avoid using a stream in a loop, because that will turn your algorithm into O(n²) when you're doing a linear loop and a linear stream operation inside it. This approach is O(n log n), for the linear stream operation and O(log n) TreeSet lookup. With a HashSet this goes down to just O(n), not that it matters much unless you're dealing with large amount of elements.
The best way I can see on how to do this would be something like IntStream.range(0, LIMIT).forEach($ -> code).
One of the reasons to use IntStream is to add parallel-ism, assuming you understand the impact of this.
IntStream.range(0, LIMIT).parallel().forEach($ -> {
// some thing thread safe.
});