Double a stream - java

I want to double a Stream (no DoubleStream). Meaning I start with a stream and want to get a new stream where each element of the old stream is streamed twice. So 1,2,3,4,4,5 gives us 1,1,2,2,3,3,4,4,4,4,5,5. Is there such a stream operation?

Create an inner stream which will contain current element two times and flatMap this stream.
stream.flatMap(e -> Stream.of(e,e))
If you want to multiply the number of elements by n you can create an utility method like this one:
public static <T> Stream<T> multiplyElements(Stream<T> in, int n) {
return in.flatMap(e -> IntStream.range(0, n).mapToObj(i -> e));
// we can also use IntStream.rangeClosed(1, n)
// but I am used to iterating from 0 to n (where n is excluded)
}
(but try to use a better name for this method, since the current one may be ambiguous)
Usage example:
multiplyElements(Stream.of(1,2), 3).forEach(System.out::println);
Output:
1
1
1
2
2
2

You can create a stream of 2 elements for each original element and flatMap it:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 4, 5);
List<Integer> doubled = list.stream().flatMap(i -> Stream.of(i, i)).collect(toList());

Here's a simple example of what biziclop has described in the comments.
static <E> Collection<E> multiply(Collection<E> source, int count) {
return new AbstractCollection<E>() {
#Override
public int size() {
return count * source.size();
}
#Override
public Iterator<E> iterator() {
return new Iterator<E>() {
final Iterator<E> it = source.iterator();
E next;
int i = 0;
#Override
public boolean hasNext() {
return i < size();
}
#Override
public E next() {
if (hasNext()) {
if ((i % count) == 0) {
next = it.next();
}
++i;
return next;
} else {
throw new NoSuchElementException();
}
}
};
}
};
}
(Working example on Ideone.)
CW'd since it wasn't my idea and the flatMap suggestions more directly answer the question.

Related

Way to remove odd values using for or forEach loop from Java arraylist [duplicate]

This question already has answers here:
Remove elements from collection while iterating
(9 answers)
Closed 1 year ago.
List<Integer> listArr = new ArrayList<>();
listArr.add(5);
listArr.add(7);
listArr.add(90);
listArr.add(11);
listArr.add(55);
listArr.add(60);
for(int i = 0; i < listArr.size(); i++) {
if (listArr.get(i) % 2 != 0) {
listArr.remove(i);
}
}
I'm trying to remove all odd numbers from the ArrayList and it must be for or foreEach loop. The result would be 7, 90, 55, 60 for the numbers that are remaining in the ArrayList after loop is finished. When I set a condition:
if(listArr.get(i) % 2 == 0)
Everything is working fine. All even numbers are removed, but in the first example that's not the case for odd numbers. Why is this happening?
Because when you remove a item in the arraylist, you've changed the list, try to iterate it in reverse mode.
break down:
when i = 0, your code removed it from list, then index 0 in your list is 7
when i = 1, the index on 1 is 90, so your code doesn't remove it.
when i =2, the index on 2 is 11, so your code remove it, then index on 2 in the list is 55,
when i = 3, the index on 3 i 60, so it will be kept.
End of loop, that's why your code output what you see, and that's why you should run it in reverse mode
You shouldn't edit list with for-loop(both add and remove), instead of use iterator like:
List<Integer> listArr = new ArrayList<>();
listArr.add(5);
listArr.add(7);
listArr.add(90);
listArr.add(11);
listArr.add(55);
listArr.add(60);
var it = listArr.iterator();
while (it.hasNext()) {
var n = it.next();
if (n % 2 == 0) {
it.remove();
}
}
The answer is just one simple line, indeed you can achieve it with many approaches with stream api, here we use Collector interface.
public class Main {
public static void main(String[] args) {
//question values
List<Integer> list = new ArrayList<>();
list.add(5);
list.add(7);
list.add(90);
list.add(11);
list.add(55);
list.add(60);
//answer
List<Integer> result = list.stream().collect(ArrayList::new, (u, v) -> {if(v % 2 == 0) u.add(v);}, List::addAll);
//validating result
result.forEach(System.out::println);
}
}
More over you can achive the same result with creating custom collector like below
public class OddNumbersCollector implements Collector<Integer, List<Integer>, List<Integer>> {
#Override
public Supplier<List<Integer>> supplier() {
return ArrayList::new;
}
#Override
public BiConsumer<List<Integer>, Integer> accumulator() {
return (u, v) -> {
if(v % 2 == 0)
u.add(v);
};
}
#Override
public BinaryOperator<List<Integer>> combiner() {
return (u, v) -> {
u.addAll(v);
return u;
};
}
#Override
public Function<List<Integer>, List<Integer>> finisher() {
return Function.identity();
}
#Override
public Set<Characteristics> characteristics() {
return Collections.unmodifiableSet(EnumSet.of(Characteristics.IDENTITY_FINISH, Characteristics.CONCURRENT));
}
}
And answer int this case becomes
List<Integer> result = list.stream().collect(new OddNumbersCollector());
That's all, no need to extra efforts .

How to implement Java 8 generic method that returns zipped stream where objects from two streams appear in turn?

I tried to implement a generic method that returns a zipped stream from two streams. The returned stream should be a concatenation of two streams where elements appear in turn, and are based on two streams that are passed to this method. If one stream is longer than another, it should contain values from the longer stream in the end. The code I have come up with is:
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Stream;
public class Task12 {
public static void main(String[] args) {
Stream<Integer> stream1 = Stream.iterate(0, integer -> integer)
.limit(20);
Stream<Integer> stream2 = Stream.iterate(1, integer -> integer)
.limit(20);
Stream<Integer> zippedStreams = zip(stream1, stream2);
zippedStreams.forEach(System.out::println);
}
private static <T> Stream<T> zip(Stream<T> first, Stream<T> second) {
Iterator<T> iterator1 = first.iterator();
Iterator<T> iterator2 = second.iterator();
List<T> elements = new LinkedList<>();
while (iterator1.hasNext() || iterator2.hasNext()) {
if (iterator1.hasNext()) {
elements.add(iterator1.next());
}
if(iterator2.hasNext()) {
elements.add(iterator2.next());
}
}
return elements.stream();
}
I have a few questions about this implementation :
is there a better way to implement it?
what if one of the streams would be an infinite Stream? Is there a way to limit the returned stream to contain exact number of elements - other than using "limit" method and passing limit as a parameter to "zip" method?
There is a way to construct the stream out of an iterator/iterable. That's very close to your solution but that way, it handles infinite stream also
public static void main(String[] args) {
Stream<Integer> stream1 = Stream.iterate(0, integer -> integer);
Stream<Integer> stream2 = Stream.iterate(1, integer -> integer)
.limit(4);
Stream<Integer> zippedStreams = StreamSupport.stream(new Ziperator<>(stream1, stream2).spliterator(), false);
zippedStreams.limit(15).forEach(System.out::println);
}
public static class Ziperator<T> implements Iterator<T>, Iterable<T>{
Iterator<T> iterator1;
Iterator<T> iterator2;
boolean even = true;
#Override
public Iterator<T> iterator() {
return this;
}
public Ziperator(Stream<T> first, Stream<T> second) {
iterator1 = first.iterator();
iterator2 = second.iterator();
}
public boolean hasNext(){
return iterator1.hasNext() || iterator2.hasNext();
}
#Override
public T next() {
if(!iterator2.hasNext()){
even = true;
}
if(!iterator1.hasNext()){
even = false;
}
if (even) {
even = false;
return iterator1.next();
} else {
even = true;
return iterator2.next();
}
}
#Override
public void remove() {
}
}
Output for that is
0
1
0
1
0
1
0
1
0
0
0
0
0
0
0
This code can be clean-up/optimized but it's a working base :)

Get random Enum from similar name or from EnumSet Java [duplicate]

How do I pick a random element from a set?
I'm particularly interested in picking a random element from a
HashSet or a LinkedHashSet, in Java.
Solutions for other languages are also welcome.
int size = myHashSet.size();
int item = new Random().nextInt(size); // In real life, the Random object should be rather more shared than this
int i = 0;
for(Object obj : myhashSet)
{
if (i == item)
return obj;
i++;
}
A somewhat related Did You Know:
There are useful methods in java.util.Collections for shuffling whole collections: Collections.shuffle(List<?>) and Collections.shuffle(List<?> list, Random rnd).
In Java 8:
static <E> E getRandomSetElement(Set<E> set) {
return set.stream().skip(new Random().nextInt(set.size())).findFirst().orElse(null);
}
Fast solution for Java using an ArrayList and a HashMap: [element -> index].
Motivation: I needed a set of items with RandomAccess properties, especially to pick a random item from the set (see pollRandom method). Random navigation in a binary tree is not accurate: trees are not perfectly balanced, which would not lead to a uniform distribution.
public class RandomSet<E> extends AbstractSet<E> {
List<E> dta = new ArrayList<E>();
Map<E, Integer> idx = new HashMap<E, Integer>();
public RandomSet() {
}
public RandomSet(Collection<E> items) {
for (E item : items) {
idx.put(item, dta.size());
dta.add(item);
}
}
#Override
public boolean add(E item) {
if (idx.containsKey(item)) {
return false;
}
idx.put(item, dta.size());
dta.add(item);
return true;
}
/**
* Override element at position <code>id</code> with last element.
* #param id
*/
public E removeAt(int id) {
if (id >= dta.size()) {
return null;
}
E res = dta.get(id);
idx.remove(res);
E last = dta.remove(dta.size() - 1);
// skip filling the hole if last is removed
if (id < dta.size()) {
idx.put(last, id);
dta.set(id, last);
}
return res;
}
#Override
public boolean remove(Object item) {
#SuppressWarnings(value = "element-type-mismatch")
Integer id = idx.get(item);
if (id == null) {
return false;
}
removeAt(id);
return true;
}
public E get(int i) {
return dta.get(i);
}
public E pollRandom(Random rnd) {
if (dta.isEmpty()) {
return null;
}
int id = rnd.nextInt(dta.size());
return removeAt(id);
}
#Override
public int size() {
return dta.size();
}
#Override
public Iterator<E> iterator() {
return dta.iterator();
}
}
This is faster than the for-each loop in the accepted answer:
int index = rand.nextInt(set.size());
Iterator<Object> iter = set.iterator();
for (int i = 0; i < index; i++) {
iter.next();
}
return iter.next();
The for-each construct calls Iterator.hasNext() on every loop, but since index < set.size(), that check is unnecessary overhead. I saw a 10-20% boost in speed, but YMMV. (Also, this compiles without having to add an extra return statement.)
Note that this code (and most other answers) can be applied to any Collection, not just Set. In generic method form:
public static <E> E choice(Collection<? extends E> coll, Random rand) {
if (coll.size() == 0) {
return null; // or throw IAE, if you prefer
}
int index = rand.nextInt(coll.size());
if (coll instanceof List) { // optimization
return ((List<? extends E>) coll).get(index);
} else {
Iterator<? extends E> iter = coll.iterator();
for (int i = 0; i < index; i++) {
iter.next();
}
return iter.next();
}
}
If you want to do it in Java, you should consider copying the elements into some kind of random-access collection (such as an ArrayList). Because, unless your set is small, accessing the selected element will be expensive (O(n) instead of O(1)). [ed: list copy is also O(n)]
Alternatively, you could look for another Set implementation that more closely matches your requirements. The ListOrderedSet from Commons Collections looks promising.
In Java:
Set<Integer> set = new LinkedHashSet<Integer>(3);
set.add(1);
set.add(2);
set.add(3);
Random rand = new Random(System.currentTimeMillis());
int[] setArray = (int[]) set.toArray();
for (int i = 0; i < 10; ++i) {
System.out.println(setArray[rand.nextInt(set.size())]);
}
List asList = new ArrayList(mySet);
Collections.shuffle(asList);
return asList.get(0);
This is identical to accepted answer (Khoth), but with the unnecessary size and i variables removed.
int random = new Random().nextInt(myhashSet.size());
for(Object obj : myhashSet) {
if (random-- == 0) {
return obj;
}
}
Though doing away with the two aforementioned variables, the above solution still remains random because we are relying upon random (starting at a randomly selected index) to decrement itself toward 0 over each iteration.
Clojure solution:
(defn pick-random [set] (let [sq (seq set)] (nth sq (rand-int (count sq)))))
Java 8+ Stream:
static <E> Optional<E> getRandomElement(Collection<E> collection) {
return collection
.stream()
.skip(ThreadLocalRandom.current()
.nextInt(collection.size()))
.findAny();
}
Based on the answer of Joshua Bone but with slight changes:
Ignores the Streams element order for a slight performance increase in parallel operations
Uses the current thread's ThreadLocalRandom
Accepts any Collection type as input
Returns the provided Optional instead of null
Perl 5
#hash_keys = (keys %hash);
$rand = int(rand(#hash_keys));
print $hash{$hash_keys[$rand]};
Here is one way to do it.
C++. This should be reasonably quick, as it doesn't require iterating over the whole set, or sorting it. This should work out of the box with most modern compilers, assuming they support tr1. If not, you may need to use Boost.
The Boost docs are helpful here to explain this, even if you don't use Boost.
The trick is to make use of the fact that the data has been divided into buckets, and to quickly identify a randomly chosen bucket (with the appropriate probability).
//#include <boost/unordered_set.hpp>
//using namespace boost;
#include <tr1/unordered_set>
using namespace std::tr1;
#include <iostream>
#include <stdlib.h>
#include <assert.h>
using namespace std;
int main() {
unordered_set<int> u;
u.max_load_factor(40);
for (int i=0; i<40; i++) {
u.insert(i);
cout << ' ' << i;
}
cout << endl;
cout << "Number of buckets: " << u.bucket_count() << endl;
for(size_t b=0; b<u.bucket_count(); b++)
cout << "Bucket " << b << " has " << u.bucket_size(b) << " elements. " << endl;
for(size_t i=0; i<20; i++) {
size_t x = rand() % u.size();
cout << "we'll quickly get the " << x << "th item in the unordered set. ";
size_t b;
for(b=0; b<u.bucket_count(); b++) {
if(x < u.bucket_size(b)) {
break;
} else
x -= u.bucket_size(b);
}
cout << "it'll be in the " << b << "th bucket at offset " << x << ". ";
unordered_set<int>::const_local_iterator l = u.begin(b);
while(x>0) {
l++;
assert(l!=u.end(b));
x--;
}
cout << "random item is " << *l << ". ";
cout << endl;
}
}
Solution above speak in terms of latency but doesn't guarantee equal probability of each index being selected.
If that needs to be considered, try reservoir sampling. http://en.wikipedia.org/wiki/Reservoir_sampling. Collections.shuffle() (as suggested by few) uses one such algorithm.
Since you said "Solutions for other languages are also welcome", here's the version for Python:
>>> import random
>>> random.choice([1,2,3,4,5,6])
3
>>> random.choice([1,2,3,4,5,6])
4
Can't you just get the size/length of the set/array, generate a random number between 0 and the size/length, then call the element whose index matches that number? HashSet has a .size() method, I'm pretty sure.
In psuedocode -
function randFromSet(target){
var targetLength:uint = target.length()
var randomIndex:uint = random(0,targetLength);
return target[randomIndex];
}
PHP, assuming "set" is an array:
$foo = array("alpha", "bravo", "charlie");
$index = array_rand($foo);
$val = $foo[$index];
The Mersenne Twister functions are better but there's no MT equivalent of array_rand in PHP.
Icon has a set type and a random-element operator, unary "?", so the expression
? set( [1, 2, 3, 4, 5] )
will produce a random number between 1 and 5.
The random seed is initialized to 0 when a program is run, so to produce different results on each run use randomize()
In C#
Random random = new Random((int)DateTime.Now.Ticks);
OrderedDictionary od = new OrderedDictionary();
od.Add("abc", 1);
od.Add("def", 2);
od.Add("ghi", 3);
od.Add("jkl", 4);
int randomIndex = random.Next(od.Count);
Console.WriteLine(od[randomIndex]);
// Can access via index or key value:
Console.WriteLine(od[1]);
Console.WriteLine(od["def"]);
Javascript solution ;)
function choose (set) {
return set[Math.floor(Math.random() * set.length)];
}
var set = [1, 2, 3, 4], rand = choose (set);
Or alternatively:
Array.prototype.choose = function () {
return this[Math.floor(Math.random() * this.length)];
};
[1, 2, 3, 4].choose();
In lisp
(defun pick-random (set)
(nth (random (length set)) set))
How about just
public static <A> A getRandomElement(Collection<A> c, Random r) {
return new ArrayList<A>(c).get(r.nextInt(c.size()));
}
For fun I wrote a RandomHashSet based on rejection sampling. It's a bit hacky, since HashMap doesn't let us access it's table directly, but it should work just fine.
It doesn't use any extra memory, and lookup time is O(1) amortized. (Because java HashTable is dense).
class RandomHashSet<V> extends AbstractSet<V> {
private Map<Object,V> map = new HashMap<>();
public boolean add(V v) {
return map.put(new WrapKey<V>(v),v) == null;
}
#Override
public Iterator<V> iterator() {
return new Iterator<V>() {
RandKey key = new RandKey();
#Override public boolean hasNext() {
return true;
}
#Override public V next() {
while (true) {
key.next();
V v = map.get(key);
if (v != null)
return v;
}
}
#Override public void remove() {
throw new NotImplementedException();
}
};
}
#Override
public int size() {
return map.size();
}
static class WrapKey<V> {
private V v;
WrapKey(V v) {
this.v = v;
}
#Override public int hashCode() {
return v.hashCode();
}
#Override public boolean equals(Object o) {
if (o instanceof RandKey)
return true;
return v.equals(o);
}
}
static class RandKey {
private Random rand = new Random();
int key = rand.nextInt();
public void next() {
key = rand.nextInt();
}
#Override public int hashCode() {
return key;
}
#Override public boolean equals(Object o) {
return true;
}
}
}
The easiest with Java 8 is:
outbound.stream().skip(n % outbound.size()).findFirst().get()
where n is a random integer. Of course it is of less performance than that with the for(elem: Col)
With Guava we can do a little better than Khoth's answer:
public static E random(Set<E> set) {
int index = random.nextInt(set.size();
if (set instanceof ImmutableSet) {
// ImmutableSet.asList() is O(1), as is .get() on the returned list
return set.asList().get(index);
}
return Iterables.get(set, index);
}
In Mathematica:
a = {1, 2, 3, 4, 5}
a[[ ⌈ Length[a] Random[] ⌉ ]]
Or, in recent versions, simply:
RandomChoice[a]
Random[] generates a pseudorandom float between 0 and 1. This is multiplied by the length of the list and then the ceiling function is used to round up to the next integer. This index is then extracted from a.
Since hash table functionality is frequently done with rules in Mathematica, and rules are stored in lists, one might use:
a = {"Badger" -> 5, "Bird" -> 1, "Fox" -> 3, "Frog" -> 2, "Wolf" -> 4};
PHP, using MT:
$items_array = array("alpha", "bravo", "charlie");
$last_pos = count($items_array) - 1;
$random_pos = mt_rand(0, $last_pos);
$random_item = $items_array[$random_pos];
you can also transfer the set to array use array
it will probably work on small scale i see the for loop in the most voted answer is O(n) anyway
Object[] arr = set.toArray();
int v = (int) arr[rnd.nextInt(arr.length)];
If you really just want to pick "any" object from the Set, without any guarantees on the randomness, the easiest is taking the first returned by the iterator.
Set<Integer> s = ...
Iterator<Integer> it = s.iterator();
if(it.hasNext()){
Integer i = it.next();
// i is a "random" object from set
}
A generic solution using Khoth's answer as a starting point.
/**
* #param set a Set in which to look for a random element
* #param <T> generic type of the Set elements
* #return a random element in the Set or null if the set is empty
*/
public <T> T randomElement(Set<T> set) {
int size = set.size();
int item = random.nextInt(size);
int i = 0;
for (T obj : set) {
if (i == item) {
return obj;
}
i++;
}
return null;
}

Split list into multiple lists with fixed number of elements in java 8

I want to something which is similar to the scala grouped function. Basically, pick 2 elements at a time and process them. Here is a reference for the same :
Split list into multiple lists with fixed number of elements
Lambdas do provide things like groupingBy and partitioningBy but none of them seem to do the same as the grouped function in Scala. Any pointers would be appreciated.
You can use Guava library.
List<Integer> bigList = ...
List<List<Integer>> smallerLists = Lists.partition(bigList, 10);
It sounds like a problem that is better handled like a low-level Stream operation just like the ops provided by the Stream API itself. A (relative) simple solution may look like:
public static <T> Stream<List<T>> chunked(Stream<T> s, int chunkSize) {
if(chunkSize<1) throw new IllegalArgumentException("chunkSize=="+chunkSize);
if(chunkSize==1) return s.map(Collections::singletonList);
Spliterator<T> src=s.spliterator();
long size=src.estimateSize();
if(size!=Long.MAX_VALUE) size=(size+chunkSize-1)/chunkSize;
int ch=src.characteristics();
ch&=Spliterator.SIZED|Spliterator.ORDERED|Spliterator.DISTINCT|Spliterator.IMMUTABLE;
ch|=Spliterator.NONNULL;
return StreamSupport.stream(new Spliterators.AbstractSpliterator<List<T>>(size, ch)
{
private List<T> current;
#Override
public boolean tryAdvance(Consumer<? super List<T>> action) {
if(current==null) current=new ArrayList<>(chunkSize);
while(current.size()<chunkSize && src.tryAdvance(current::add));
if(!current.isEmpty()) {
action.accept(current);
current=null;
return true;
}
return false;
}
}, s.isParallel());
}
Simple test:
chunked(Stream.of(1, 2, 3, 4, 5, 6, 7), 3)
.parallel().forEachOrdered(System.out::println);
The advantage is that you do not need a full collection of all items for subsequent stream processing, e.g.
chunked(
IntStream.range(0, 1000).mapToObj(i -> {
System.out.println("processing item "+i);
return i;
}), 2).anyMatch(list->list.toString().equals("[6, 7]")));
will print:
processing item 0
processing item 1
processing item 2
processing item 3
processing item 4
processing item 5
processing item 6
processing item 7
true
rather than processing a thousand items of IntStream.range(0, 1000). This also enables using infinite source Streams:
chunked(Stream.iterate(0, i->i+1), 2).anyMatch(list->list.toString().equals("[6, 7]")));
If you are interested in a fully materialized collection rather than applying subsequent Stream operations, you may simply use the following operation:
List<Integer> list=Arrays.asList(1, 2, 3, 4, 5, 6, 7);
int listSize=list.size(), chunkSize=2;
List<List<Integer>> list2=
IntStream.range(0, (listSize-1)/chunkSize+1)
.mapToObj(i->list.subList(i*=chunkSize,
listSize-chunkSize>=i? i+chunkSize: listSize))
.collect(Collectors.toList());
You can create your own collector. Something like this:
class GroupingCollector<T> implements Collector<T, List<List<T>>, List<List<T>>> {
private final int elementCountInGroup;
public GroupingCollector(int elementCountInGroup) {
this.elementCountInGroup = elementCountInGroup;
}
#Override
public Supplier<List<List<T>>> supplier() {
return ArrayList::new;
}
#Override
public BiConsumer<List<List<T>>, T> accumulator() {
return (lists, integer) -> {
if (!lists.isEmpty()) {
List<T> integers = lists.get(lists.size() - 1);
if (integers.size() < elementCountInGroup) {
integers.add(integer);
return;
}
}
List<T> list = new ArrayList<>();
list.add(integer);
lists.add(list);
};
}
#Override
public BinaryOperator<List<List<T>>> combiner() {
return (lists, lists2) -> {
List<List<T>> r = new ArrayList<>();
r.addAll(lists);
r.addAll(lists2);
return r;
};
}
#Override
public Function<List<List<T>>, List<List<T>>> finisher() {
return lists -> lists;
}
#Override
public Set<Characteristics> characteristics() {
return Collections.emptySet();
}
}
And then you can use it in a way like this:
List<List<Integer>> collect = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10).collect(new GroupingCollector<>(3));
System.out.println(collect);
Will print:
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
A recursive solution to transform the list to a list-of-lists would also be possible
int chunkSize = 2;
private <T> List<List<T>> process(List<T> list) {
if (list.size() > chunkSize) {
List<T> chunk = list.subList(0, chunkSize);
List<T> rest = list.subList(chunkSize, list.size());
List<List<T>> lists = process(rest);
return concat(chunk, lists);
} else {
ArrayList<List<T>> retVal = new ArrayList<>();
retVal.add(list);
return retVal;
}
}
private <T> List<List<T>> concat(List<T> chunk, List<List<T>> rest) {
rest.add(0, chunk);
return rest;
}
You could write your own collector finisher, similar to
final List<String> strings = Arrays.asList("Hello", "World", "I", "Am", "You");
final int size = 3;
final List<List<String>> stringLists = strings.stream()
.collect(Collectors.collectingAndThen(Collectors.toList(), new Function<List<String>, List<List<String>>>() {
#Override
public List<List<String>> apply(List<String> strings) {
final List<List<String>> result = new ArrayList<>();
int counter = 0;
List<String> stringsToAdd = new ArrayList<>();
for (final String string : strings) {
if (counter == 0) {
result.add(stringsToAdd);
} else {
if (counter == size) {
stringsToAdd = new ArrayList<>();
result.add(stringsToAdd);
counter = 0;
}
}
++counter;
stringsToAdd.add(string);
}
return result;
}
}));
System.out.println("stringLists = " + stringLists); // stringLists = [[Hello, World, I], [Am, You]]
A simple version with java 8 streams api:
static <T> List<List<T>> partition(List<T> list, Integer partitionSize) {
int numberOfLists = BigDecimal.valueOf(list.size())
.divide(BigDecimal.valueOf(partitionSize), 0, CEILING)
.intValue();
return IntStream.range(0, numberOfLists)
.mapToObj(it -> list.subList(it * partitionSize, Math.min((it+1) * partitionSize, list.size())))
.collect(Collectors.toList());
}

How to create an infinite Stream<E> out of an Iterator<E>?

Looking at the following class I've made:
public class FibonacciSupplier implements Iterator<Integer> {
private final IntPredicate hasNextPredicate;
private int beforePrevious = 0;
private int previous = 1;
private FibonacciSupplier(final IntPredicate hasNextPredicate) {
this.hasNextPredicate = hasNextPredicate;
}
#Override
public boolean hasNext() {
return hasNextPredicate.test(previous);
}
#Override
public Integer next() {
int result = beforePrevious + previous;
beforePrevious = previous;
previous = result;
return result;
}
public static FibonacciSupplier infinite() {
return new FibonacciSupplier(i -> true);
}
public static FibonacciSupplier finite(final IntPredicate predicate) {
return new FibonacciSupplier(predicate);
}
}
And the usage of it in:
public class Problem2 extends Problem<Integer> {
#Override
public void run() {
result = toList(FibonacciSupplier.finite(i -> (i <= 4_000_000)))
.stream()
.filter(i -> (i % 2 == 0))
.mapToInt(i -> i)
.sum();
}
#Override
public String getName() {
return "Problem 2";
}
private static <E> List<E> toList(final Iterator<E> iterator) {
List<E> list = new ArrayList<>();
while (iterator.hasNext()) {
list.add(iterator.next());
}
return list;
}
}
How would I be able to create an infinite Stream<E>?
If I were to use Stream<Integer> infiniteStream = toList(FibonacciSupplier.infinite()).stream(), I would, possibly surprisingly, never get an infinite stream.
Instead the code would loop forever in the creation of the list in an underlying method.
This so far is purely theoretical, but I can definately understand the need for it if I would want to first skip the first x numbers from an infinite stream, and then limit it by the last y numbers, something like:
int x = MAGIC_NUMBER_X;
int y = MAGIC_NUMBER_y;
int sum = toList(FibonacciSupplier.infinite())
.stream()
.skip(x)
.limit(y)
.mapToInt(i -> i)
.sum();
The code would not ever return a result, how should it be done?
Your mistake is to think that you need an Iterator or a Collection to create a Stream. For creating an infinite stream, a single method providing one value after another is enough. So for your class FibonacciSupplier the simplest use is:
IntStream s=IntStream.generate(FibonacciSupplier.infinite()::next);
or, if you prefer boxed values:
Stream<Integer> s=Stream.generate(FibonacciSupplier.infinite()::next);
Note that in this case the method does not have to be named next nor fulfill the Iterator interface. But it doesn’t matter if it does as with your class. Further, as we just told the stream to use the next method as a Supplier, the hasNext method will never be called. It’s just infinite.
Creating a finite stream using your Iterator is a bit more complicated:
Stream<Integer> s=StreamSupport.stream(
Spliterators.spliteratorUnknownSize(
FibonacciSupplier.finite(intPredicate), Spliterator.ORDERED),
false);
In this case if you want a finite IntStream with unboxed int values your FibonacciSupplier should implement PrimitiveIterator.OfInt.
In Java 8 there are no public, concrete classes implementing the interface Stream. However, there are some static factory methods. One of the most important is StreamSupport.stream. In particular, it is used in the default method Collection.stream –inherited by most collection classes:
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
The default implementation of this method creates a Spliterator by invoking spliterator(), and passes the created object to the factory method. Spliterator is a new interface introduced with Java 8 to support parallel streams. It is similar to Iterator, but in contrast to the latter, a Spliterator can be divided into parts, that can be processed independently. See Spliterator.trySplit for details.
The default method Iterable.spliterator was also added in Java 8, so that every Iterable class automatically supports Spliterators. The implementation looks as follows:
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
The method creates the Spliterator from an arbitrary Iterator. If you combine these two steps, you can create a Stream from an arbitrary Iterator:
<T> Stream<T> stream(Iterator<T> iterator) {
Spliterator<T> spliterator
= Spliterators.spliteratorUnknownSize(iterator, 0);
return StreamSupport.stream(spliterator, false);
}
To get an impression of Spliterators, here is a very simple example without using collections. The following class implements Spliterator to iterate over a half-open interval of integers:
public final class IntRange implements Spliterator.OfInt {
private int first, last;
public IntRange(int first, int last) {
this.first = first;
this.last = last;
}
public boolean tryAdvance(IntConsumer action) {
if (first < last) {
action.accept(first++);
return true;
} else {
return false;
}
}
public OfInt trySplit() {
int size = last - first;
if (size >= 10) {
int temp = first;
first += size / 2;
return new IntRange(temp, first);
} else {
return null;
}
}
public long estimateSize() {
return Math.max(last - first, 0);
}
public int characteristics() {
return ORDERED | DISTINCT | SIZED | NONNULL
| IMMUTABLE | CONCURRENT | SUBSIZED;
}
}
You can use the low level stream support primitives and the Spliterators library to make a stream out of an Iterator.
The last parameter to StreamSupport.stream() says that the stream is not parallel. Be sure to let it like that because your Fibonacci iterator depends on previous iterations.
return StreamSupport.stream( Spliterators.spliteratorUnknownSize( new Iterator<Node>()
{
#Override
public boolean hasNext()
{
// to implement
return ...;
}
#Override
public ContentVersion next()
{
// to implement
return ...;
}
}, Spliterator.ORDERED ), false );
To add another answer, perhaps AbstractSpliterator is a better choice, especially given the example code. Generate is inflexible as there is no [good] way to give a stop condition except by using limit. Limit only accepts a number of items rather than a predicate, so we have to know how many items we want to generate - which might not be possible, and what if the generator is a black box passed to us?
AbstractSpliterator is a halfway house between having to write a whole spliterator, and using Iterator/Iterable. AbstractSpliterator lacks just the tryAdvance method where we first check our predicate for being done, and if not pass the generated value to an action. Here's an example of a Fibonacci sequence using AbstractIntSpliterator:
public class Fibonacci {
private static class FibonacciGenerator extends Spliterators.AbstractIntSpliterator
{
private IntPredicate hasNextPredicate;
private int beforePrevious = 0;
private int previous = 0;
protected FibonacciGenerator(IntPredicate hasNextPredicate)
{
super(Long.MAX_VALUE, 0);
this.hasNextPredicate = hasNextPredicate;
}
#Override
public boolean tryAdvance(IntConsumer action)
{
if (action == null)
{
throw new NullPointerException();
}
int next = Math.max(1, beforePrevious + previous);
beforePrevious = previous;
previous = next;
if (!hasNextPredicate.test(next))
{
return false;
}
action.accept(next);
return true;
}
#Override
public boolean tryAdvance(Consumer<? super Integer> action)
{
if (action == null)
{
throw new NullPointerException();
}
int next = Math.max(1, beforePrevious + previous);
beforePrevious = previous;
previous = next;
if (!hasNextPredicate.test(next))
{
return false;
}
action.accept(next);
return true;
}
}
public static void main(String args[])
{
Stream<Integer> infiniteStream = StreamSupport.stream(
new FibonacciGenerator(i -> true), false);
Stream<Integer> finiteStream = StreamSupport.stream(
new FibonacciGenerator(i -> i < 100), false);
// Print with a side-effect for the demo
infiniteStream.limit(10).forEach(System.out::println);
finiteStream.forEach(System.out::println);
}
}
For more details I've covered generators in Java 8 in my blog http://thecannycoder.wordpress.com/

Categories

Resources