java 8: map function w/ two stream inputs? [duplicate] - functional-programming
In JDK 8 with lambda b93 there was a class java.util.stream.Streams.zip in b93 which could be used to zip streams (this is illustrated in the tutorial Exploring Java8 Lambdas. Part 1 by Dhananjay Nene). This function :
Creates a lazy and sequential combined Stream whose elements are the
result of combining the elements of two streams.
However in b98 this has disappeared. Infact the Streams class is not even accessible in java.util.stream in b98.
Has this functionality been moved, and if so how do I zip streams concisely using b98?
The application I have in mind is in this java implementation of Shen, where I replaced the zip functionality in the
static <T> boolean every(Collection<T> c1, Collection<T> c2, BiPredicate<T, T> pred)
static <T> T find(Collection<T> c1, Collection<T> c2, BiPredicate<T, T> pred)
functions with rather verbose code (which doesn't use functionality from b98).
I needed this as well so I just took the source code from b93 and put it in a "util" class. I had to modify it slightly to work with the current API.
For reference here's the working code (take it at your own risk...):
public static<A, B, C> Stream<C> zip(Stream<? extends A> a,
Stream<? extends B> b,
BiFunction<? super A, ? super B, ? extends C> zipper) {
Objects.requireNonNull(zipper);
Spliterator<? extends A> aSpliterator = Objects.requireNonNull(a).spliterator();
Spliterator<? extends B> bSpliterator = Objects.requireNonNull(b).spliterator();
// Zipping looses DISTINCT and SORTED characteristics
int characteristics = aSpliterator.characteristics() & bSpliterator.characteristics() &
~(Spliterator.DISTINCT | Spliterator.SORTED);
long zipSize = ((characteristics & Spliterator.SIZED) != 0)
? Math.min(aSpliterator.getExactSizeIfKnown(), bSpliterator.getExactSizeIfKnown())
: -1;
Iterator<A> aIterator = Spliterators.iterator(aSpliterator);
Iterator<B> bIterator = Spliterators.iterator(bSpliterator);
Iterator<C> cIterator = new Iterator<C>() {
#Override
public boolean hasNext() {
return aIterator.hasNext() && bIterator.hasNext();
}
#Override
public C next() {
return zipper.apply(aIterator.next(), bIterator.next());
}
};
Spliterator<C> split = Spliterators.spliterator(cIterator, zipSize, characteristics);
return (a.isParallel() || b.isParallel())
? StreamSupport.stream(split, true)
: StreamSupport.stream(split, false);
}
zip is one of the functions provided by the protonpack library.
Stream<String> streamA = Stream.of("A", "B", "C");
Stream<String> streamB = Stream.of("Apple", "Banana", "Carrot", "Doughnut");
List<String> zipped = StreamUtils.zip(streamA,
streamB,
(a, b) -> a + " is for " + b)
.collect(Collectors.toList());
assertThat(zipped,
contains("A is for Apple", "B is for Banana", "C is for Carrot"));
If you have Guava in your project, you can use the Streams.zip method (was added in Guava 21):
Returns a stream in which each element is the result of passing the corresponding element of each of streamA and streamB to function. The resulting stream will only be as long as the shorter of the two input streams; if one stream is longer, its extra elements will be ignored. The resulting stream is not efficiently splittable. This may harm parallel performance.
public class Streams {
...
public static <A, B, R> Stream<R> zip(Stream<A> streamA,
Stream<B> streamB, BiFunction<? super A, ? super B, R> function) {
...
}
}
Zipping two streams using JDK8 with lambda (gist).
public static <A, B, C> Stream<C> zip(Stream<A> streamA, Stream<B> streamB, BiFunction<A, B, C> zipper) {
final Iterator<A> iteratorA = streamA.iterator();
final Iterator<B> iteratorB = streamB.iterator();
final Iterator<C> iteratorC = new Iterator<C>() {
#Override
public boolean hasNext() {
return iteratorA.hasNext() && iteratorB.hasNext();
}
#Override
public C next() {
return zipper.apply(iteratorA.next(), iteratorB.next());
}
};
final boolean parallel = streamA.isParallel() || streamB.isParallel();
return iteratorToFiniteStream(iteratorC, parallel);
}
public static <T> Stream<T> iteratorToFiniteStream(Iterator<T> iterator, boolean parallel) {
final Iterable<T> iterable = () -> iterator;
return StreamSupport.stream(iterable.spliterator(), parallel);
}
Since I can't conceive any use of zipping on collections other than indexed ones (Lists) and I am a big fan of simplicity, this would be my solution:
<A,B,C> Stream<C> zipped(List<A> lista, List<B> listb, BiFunction<A,B,C> zipper){
int shortestLength = Math.min(lista.size(),listb.size());
return IntStream.range(0,shortestLength).mapToObj( i -> {
return zipper.apply(lista.get(i), listb.get(i));
});
}
The methods of the class you mentioned have been moved to the Stream interface itself in favor to the default methods. But it seems that the zip method has been removed. Maybe because it is not clear what the default behavior for different sized streams should be. But implementing the desired behavior is straight-forward:
static <T> boolean every(
Collection<T> c1, Collection<T> c2, BiPredicate<T, T> pred) {
Iterator<T> it=c2.iterator();
return c1.stream().allMatch(x->!it.hasNext()||pred.test(x, it.next()));
}
static <T> T find(Collection<T> c1, Collection<T> c2, BiPredicate<T, T> pred) {
Iterator<T> it=c2.iterator();
return c1.stream().filter(x->it.hasNext()&&pred.test(x, it.next()))
.findFirst().orElse(null);
}
I humbly suggest this implementation. The resulting stream is truncated to the shorter of the two input streams.
public static <L, R, T> Stream<T> zip(Stream<L> leftStream, Stream<R> rightStream, BiFunction<L, R, T> combiner) {
Spliterator<L> lefts = leftStream.spliterator();
Spliterator<R> rights = rightStream.spliterator();
return StreamSupport.stream(new AbstractSpliterator<T>(Long.min(lefts.estimateSize(), rights.estimateSize()), lefts.characteristics() & rights.characteristics()) {
#Override
public boolean tryAdvance(Consumer<? super T> action) {
return lefts.tryAdvance(left->rights.tryAdvance(right->action.accept(combiner.apply(left, right))));
}
}, leftStream.isParallel() || rightStream.isParallel());
}
Using the latest Guava library (for the Streams class) you should be able to do
final Map<String, String> result =
Streams.zip(
collection1.stream(),
collection2.stream(),
AbstractMap.SimpleEntry::new)
.collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()));
The Lazy-Seq library provides zip functionality.
https://github.com/nurkiewicz/LazySeq
This library is heavily inspired by scala.collection.immutable.Stream and aims to provide immutable, thread-safe and easy to use lazy sequence implementation, possibly infinite.
Would this work for you? It's a short function, which lazily evaluates over the streams it's zipping, so you can supply it with infinite streams (it doesn't need to take the size of the streams being zipped).
If the streams are finite it stops as soon as one of the streams runs out of elements.
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.stream.Stream;
class StreamUtils {
static <ARG1, ARG2, RESULT> Stream<RESULT> zip(
Stream<ARG1> s1,
Stream<ARG2> s2,
BiFunction<ARG1, ARG2, RESULT> combiner) {
final var i2 = s2.iterator();
return s1.map(x1 -> i2.hasNext() ? combiner.apply(x1, i2.next()) : null)
.takeWhile(Objects::nonNull);
}
}
Here is some unit test code (much longer than the code itself!)
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiFunction;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.junit.jupiter.api.Assertions.assertEquals;
class StreamUtilsTest {
#ParameterizedTest
#MethodSource("shouldZipTestCases")
<ARG1, ARG2, RESULT>
void shouldZip(
String testName,
Stream<ARG1> s1,
Stream<ARG2> s2,
BiFunction<ARG1, ARG2, RESULT> combiner,
Stream<RESULT> expected) {
var actual = StreamUtils.zip(s1, s2, combiner);
assertEquals(
expected.collect(Collectors.toList()),
actual.collect(Collectors.toList()),
testName);
}
private static Stream<Arguments> shouldZipTestCases() {
return Stream.of(
Arguments.of(
"Two empty streams",
Stream.empty(),
Stream.empty(),
(BiFunction<Object, Object, Object>) StreamUtilsTest::combine,
Stream.empty()),
Arguments.of(
"One singleton and one empty stream",
Stream.of(1),
Stream.empty(),
(BiFunction<Object, Object, Object>) StreamUtilsTest::combine,
Stream.empty()),
Arguments.of(
"One empty and one singleton stream",
Stream.empty(),
Stream.of(1),
(BiFunction<Object, Object, Object>) StreamUtilsTest::combine,
Stream.empty()),
Arguments.of(
"Two singleton streams",
Stream.of("blah"),
Stream.of(1),
(BiFunction<Object, Object, Object>) StreamUtilsTest::combine,
Stream.of(pair("blah", 1))),
Arguments.of(
"One singleton, one multiple stream",
Stream.of("blob"),
Stream.of(2, 3),
(BiFunction<Object, Object, Object>) StreamUtilsTest::combine,
Stream.of(pair("blob", 2))),
Arguments.of(
"One multiple, one singleton stream",
Stream.of("foo", "bar"),
Stream.of(4),
(BiFunction<Object, Object, Object>) StreamUtilsTest::combine,
Stream.of(pair("foo", 4))),
Arguments.of(
"Two multiple streams",
Stream.of("nine", "eleven"),
Stream.of(10, 12),
(BiFunction<Object, Object, Object>) StreamUtilsTest::combine,
Stream.of(pair("nine", 10), pair("eleven", 12)))
);
}
private static List<Object> pair(Object o1, Object o2) {
return List.of(o1, o2);
}
static private <T1, T2> List<Object> combine(T1 o1, T2 o2) {
return List.of(o1, o2);
}
#Test
void shouldLazilyEvaluateInZip() {
final var a = new AtomicInteger();
final var b = new AtomicInteger();
final var zipped = StreamUtils.zip(
Stream.generate(a::incrementAndGet),
Stream.generate(b::decrementAndGet),
(xa, xb) -> xb + 3 * xa);
assertEquals(0, a.get(), "Should not have evaluated a at start");
assertEquals(0, b.get(), "Should not have evaluated b at start");
final var takeTwo = zipped.limit(2);
assertEquals(0, a.get(), "Should not have evaluated a at take");
assertEquals(0, b.get(), "Should not have evaluated b at take");
final var list = takeTwo.collect(Collectors.toList());
assertEquals(2, a.get(), "Should have evaluated a after collect");
assertEquals(-2, b.get(), "Should have evaluated b after collect");
assertEquals(List.of(2, 4), list);
}
}
public class Tuple<S,T> {
private final S object1;
private final T object2;
public Tuple(S object1, T object2) {
this.object1 = object1;
this.object2 = object2;
}
public S getObject1() {
return object1;
}
public T getObject2() {
return object2;
}
}
public class StreamUtils {
private StreamUtils() {
}
public static <T> Stream<Tuple<Integer,T>> zipWithIndex(Stream<T> stream) {
Stream<Integer> integerStream = IntStream.range(0, Integer.MAX_VALUE).boxed();
Iterator<Integer> integerIterator = integerStream.iterator();
return stream.map(x -> new Tuple<>(integerIterator.next(), x));
}
}
AOL's cyclops-react, to which I contribute, also provides zipping functionality, both via an extended Stream implementation, that also implements the reactive-streams interface ReactiveSeq, and via StreamUtils that offers much of the same functionality via static methods to standard Java Streams.
List<Tuple2<Integer,Integer>> list = ReactiveSeq.of(1,2,3,4,5,6)
.zip(Stream.of(100,200,300,400));
List<Tuple2<Integer,Integer>> list = StreamUtils.zip(Stream.of(1,2,3,4,5,6),
Stream.of(100,200,300,400));
It also offers more generalized Applicative based zipping. E.g.
ReactiveSeq.of("a","b","c")
.ap3(this::concat)
.ap(of("1","2","3"))
.ap(of(".","?","!"))
.toList();
//List("a1.","b2?","c3!");
private String concat(String a, String b, String c){
return a+b+c;
}
And even the ability to pair every item in one stream with every item in another
ReactiveSeq.of("a","b","c")
.forEach2(str->Stream.of(str+"!","2"), a->b->a+"_"+b);
//ReactiveSeq("a_a!","a_2","b_b!","b_2","c_c!","c2")
If anyone needs this yet, there is StreamEx.zipWith function in streamex library:
StreamEx<String> givenNames = StreamEx.of("Leo", "Fyodor")
StreamEx<String> familyNames = StreamEx.of("Tolstoy", "Dostoevsky")
StreamEx<String> fullNames = givenNames.zipWith(familyNames, (gn, fn) -> gn + " " + fn);
fullNames.forEach(System.out::println); // prints: "Leo Tolstoy\nFyodor Dostoevsky\n"
This is great. I had to zip two streams into a Map with one stream being the key and other being the value
Stream<String> streamA = Stream.of("A", "B", "C");
Stream<String> streamB = Stream.of("Apple", "Banana", "Carrot", "Doughnut");
final Stream<Map.Entry<String, String>> s = StreamUtils.zip(streamA,
streamB,
(a, b) -> {
final Map.Entry<String, String> entry = new AbstractMap.SimpleEntry<String, String>(a, b);
return entry;
});
System.out.println(s.collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue())));
Output:
{A=Apple, B=Banana, C=Carrot}
Related
in dart, is there any way to limit the key in some special strings
i search many place, did not find any solution. so the question is. i want a map in dart like this var Map<String, String> data; it will be a params init and passed in other place. but when pass the params, i want to limit the key in map only accept some special strings. like 'someA', 'someB'. so,when call the function it like this. functionA({'someA': 'xxxx', 'someB': 'xxxx'}) no other keys. and also when i call the function i can just type some word and the IDE will show suggestion for me to select the key. the all code like this (can not run). var List<String> keyList = ['someA', 'someB']; class Abc { functionA({Map<valueOf keyList, String> data) { } } Abc().functionA({'someA': 'xxxx', 'someB': 'xxxx'});
You can provide your own Map implementation (deriving from DelegatingMap from package:collection would make it a lot easier) and then override operator []= to throw if the supplied key should not be allowed. For example: import 'package:collection/collection.dart'; /// A [Map] that allows only certain keys. class LimitedMap<K, V> extends DelegatingMap<K, V> { LimitedMap({Iterable<K> allowedKeys}) : allowedKeys = <K>{...allowedKeys}, super(<K, V>{}); final Set<K> allowedKeys; /// Throws an exception if [key] is not allowed. void _checkKey(K key) { if (!allowedKeys.contains(key)) { throw Exception('Invalid key: $key'); } } #override void addAll(Map<K, V> other) => addEntries(other.entries); #override void addEntries(Iterable<MapEntry<K, V>> entries) { for (var entry in entries) { this[entry.key] = entry.value; } } #override V putIfAbsent(K key, V Function() ifAbsent) { _checkKey(key); return super.putIfAbsent(key, ifAbsent); } #override V update(K key, V Function(V) update, {V Function() ifAbsent}) { _checkKey(key); return super.update(key, update, ifAbsent: ifAbsent); } #override void operator []=(K key, V value) { _checkKey(key); super[key] = value; } } class MyMap extends LimitedMap<String, String> { MyMap([Map<String, String> initialMap]) : super(allowedKeys: {'foo', 'bar', 'baz'}) { if (initialMap != null) { addAll(initialMap); } } } Alternatively, if your keys are fixed, it'd be better to just make them properties on a custom class, and then you also would get the IDE autocompletion behavior that you want.
HashSet and Dictionary in TypeScript: export of Interface
I think I need some feedback on my collection classes - still learning typescript and javascript and these implementations can surely be improved. I am looking forward to any suggestion. I think I do use the generic types in a useful way, any advice here would be appreciated. The answer I am looking for most is removing the duplicate IHashTable definition from the end of both snippets and moving it to its own file, I cannot get that done it seems. I am even unsure if this IS an interface in the first place. It compiles and works this way, as far as I can see. The collection types are incomplete and only define the basic most function at the moment. Once I am sure I use the language and its features correct the other functions should not be too difficult. Here is my HashSet: import { IHashable } from "./IHashable" export class HashSet<T extends IHashable> { private _items: HashTable<T>; public constructor() { this._items = {}; } public Add(key: T): void { let str: string = key.GetHash(); if (this._items[str] == null) { this._items[str] = key; } else { throw new RangeError("Key '" + str + "' already exists."); } } public Contains(key: T): boolean { let str: string = key.GetHash(); return this._items[str] != null; } } interface HashTable<T> { [key: string]: T; } I wonder if I can avoid the checking-before-adding in a way. The javascript-dictionary this relies on does allow duplicates, so to avoid them there is no other way than to check myself? This is my Dictionary: import { IHashable } from "./IHashable" export class Dictionary<T1 extends IHashable, T2> { private _items: HashTable<KeyValuePair<T1, T2>>; public constructor() { this._items = {}; } public Add(key: T1, value: T2) { let str: string = key.GetHash(); if (this._items[str] == null) { let kvp: KeyValuePair<T1, T2> = new KeyValuePair(key, value); this._items[str] = kvp; } else { throw new RangeError("Key '" + str + "' already exists."); } } public ContainsKey(key: T1): boolean { let str: string = key.GetHash(); return this._items[str] != null; } public Get(key: T1): T2 { let str: string = key.GetHash(); let kvp: KeyValuePair<T1, T2> = this._items[str]; if (kvp == null) throw new RangeError("Key '" + str + "' not found") return kvp.Value; } } export class KeyValuePair<T1 extends IHashable, T2> { private _key: T1; private _value: T2; public get Key(): T1 { return this._key; } public get Value(): T2 { return this._value; } public constructor(key: T1, value: T2) { this._key = key; this._value = value; } } interface HashTable<T> { [key: string]: T; } Both rely on a definition of IHashable (hashABLE and hashTABLE: I should find other names.) export interface IHashable { GetHash(): string; } The dictionary looks a bit strange, it "wraps" my dictionary into a new type KeyValuePair and then uses this in the javascript dictionary. What I hope to gain by doing this is get my own type for key, in and out, as long as it offers a string by which it can be indexed. - No idea if that makes sense or is completly wrong. What I am missing is the count of items in the collection, a way to remove items, and a way to iterate over the keys and the values. Regarding iterating over I will post another question with my implementation of a list and a ForEach over it, hoping iterating the keys or values might be possible in the same way. Probably the most important question I forgot here: How could the GetHash-Method be build for an own class? I was going to have a static number on my classes, and count up by 1 in the constructor before assign this number to each instance. This would guarantee uniqueness... is there something better? Thanks for any tip! Ralf
What's the Java 8 equivalent of zipWithIndex method in Scala List? [duplicate]
Is there a concise way to iterate over a stream whilst having access to the index in the stream? String[] names = {"Sam","Pamela", "Dave", "Pascal", "Erik"}; List<String> nameList; Stream<Integer> indices = intRange(1, names.length).boxed(); nameList = zip(indices, stream(names), SimpleEntry::new) .filter(e -> e.getValue().length() <= e.getKey()) .map(Entry::getValue) .collect(toList()); which seems rather disappointing compared to the LINQ example given there string[] names = { "Sam", "Pamela", "Dave", "Pascal", "Erik" }; var nameList = names.Where((c, index) => c.Length <= index + 1).ToList(); Is there a more concise way? Further it seems the zip has either moved or been removed...
The cleanest way is to start from a stream of indices: String[] names = {"Sam", "Pamela", "Dave", "Pascal", "Erik"}; IntStream.range(0, names.length) .filter(i -> names[i].length() <= i) .mapToObj(i -> names[i]) .collect(Collectors.toList()); The resulting list contains "Erik" only. One alternative which looks more familiar when you are used to for loops would be to maintain an ad hoc counter using a mutable object, for example an AtomicInteger: String[] names = {"Sam", "Pamela", "Dave", "Pascal", "Erik"}; AtomicInteger index = new AtomicInteger(); List<String> list = Arrays.stream(names) .filter(n -> n.length() <= index.incrementAndGet()) .collect(Collectors.toList()); Note that using the latter method on a parallel stream could break as the items would not necesarily be processed "in order".
The Java 8 streams API lacks the features of getting the index of a stream element as well as the ability to zip streams together. This is unfortunate, as it makes certain applications (like the LINQ challenges) more difficult than they would be otherwise. There are often workarounds, however. Usually this can be done by "driving" the stream with an integer range, and taking advantage of the fact that the original elements are often in an array or in a collection accessible by index. For example, the Challenge 2 problem can be solved this way: String[] names = {"Sam", "Pamela", "Dave", "Pascal", "Erik"}; List<String> nameList = IntStream.range(0, names.length) .filter(i -> names[i].length() <= i) .mapToObj(i -> names[i]) .collect(toList()); As I mentioned above, this takes advantage of the fact that the data source (the names array) is directly indexable. If it weren't, this technique wouldn't work. I'll admit that this doesn't satisfy the intent of Challenge 2. Nonetheless it does solve the problem reasonably effectively. EDIT My previous code example used flatMap to fuse the filter and map operations, but this was cumbersome and provided no advantage. I've updated the example per the comment from Holger.
Since guava 21, you can use Streams.mapWithIndex() Example (from official doc): Streams.mapWithIndex( Stream.of("a", "b", "c"), (str, index) -> str + ":" + index) ) // will return Stream.of("a:0", "b:1", "c:2")
I've used the following solution in my project. I think it is better than using mutable objects or integer ranges. import java.util.*; import java.util.function.*; import java.util.stream.Collector; import java.util.stream.Collector.Characteristics; import java.util.stream.Stream; import java.util.stream.StreamSupport; import static java.util.Objects.requireNonNull; public class CollectionUtils { private CollectionUtils() { } /** * Converts an {#link java.util.Iterator} to {#link java.util.stream.Stream}. */ public static <T> Stream<T> iterate(Iterator<? extends T> iterator) { int characteristics = Spliterator.ORDERED | Spliterator.IMMUTABLE; return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, characteristics), false); } /** * Zips the specified stream with its indices. */ public static <T> Stream<Map.Entry<Integer, T>> zipWithIndex(Stream<? extends T> stream) { return iterate(new Iterator<Map.Entry<Integer, T>>() { private final Iterator<? extends T> streamIterator = stream.iterator(); private int index = 0; #Override public boolean hasNext() { return streamIterator.hasNext(); } #Override public Map.Entry<Integer, T> next() { return new AbstractMap.SimpleImmutableEntry<>(index++, streamIterator.next()); } }); } /** * Returns a stream consisting of the results of applying the given two-arguments function to the elements of this stream. * The first argument of the function is the element index and the second one - the element value. */ public static <T, R> Stream<R> mapWithIndex(Stream<? extends T> stream, BiFunction<Integer, ? super T, ? extends R> mapper) { return zipWithIndex(stream).map(entry -> mapper.apply(entry.getKey(), entry.getValue())); } public static void main(String[] args) { String[] names = {"Sam", "Pamela", "Dave", "Pascal", "Erik"}; System.out.println("Test zipWithIndex"); zipWithIndex(Arrays.stream(names)).forEach(entry -> System.out.println(entry)); System.out.println(); System.out.println("Test mapWithIndex"); mapWithIndex(Arrays.stream(names), (Integer index, String name) -> index+"="+name).forEach((String s) -> System.out.println(s)); } }
In addition to protonpack, jOOλ's Seq provides this functionality (and by extension libraries that build on it like cyclops-react, I am the author of this library). Seq.seq(Stream.of(names)).zipWithIndex() .filter( namesWithIndex -> namesWithIndex.v1.length() <= namesWithIndex.v2 + 1) .toList(); Seq also supports just Seq.of(names) and will build a JDK Stream under the covers. The simple-react equivalent would similarly look like LazyFutureStream.of(names) .zipWithIndex() .filter( namesWithIndex -> namesWithIndex.v1.length() <= namesWithIndex.v2 + 1) .toList(); The simple-react version is more tailored for asynchronous / concurrent processing.
Just for completeness here's the solution involving my StreamEx library: String[] names = {"Sam","Pamela", "Dave", "Pascal", "Erik"}; EntryStream.of(names) .filterKeyValue((idx, str) -> str.length() <= idx+1) .values().toList(); Here we create an EntryStream<Integer, String> which extends Stream<Entry<Integer, String>> and adds some specific operations like filterKeyValue or values. Also toList() shortcut is used.
I found the solutions here when the Stream is created of list or array (and you know the size). But what if Stream is with unknown size? In this case try this variant: public class WithIndex<T> { private int index; private T value; WithIndex(int index, T value) { this.index = index; this.value = value; } public int index() { return index; } public T value() { return value; } #Override public String toString() { return value + "(" + index + ")"; } public static <T> Function<T, WithIndex<T>> indexed() { return new Function<T, WithIndex<T>>() { int index = 0; #Override public WithIndex<T> apply(T t) { return new WithIndex<>(index++, t); } }; } } Usage: public static void main(String[] args) { Stream<String> stream = Stream.of("a", "b", "c", "d", "e"); stream.map(WithIndex.indexed()).forEachOrdered(e -> { System.out.println(e.index() + " -> " + e.value()); }); }
With a List you can try List<String> strings = new ArrayList<>(Arrays.asList("First", "Second", "Third", "Fourth", "Fifth")); // An example list of Strings strings.stream() // Turn the list into a Stream .collect(HashMap::new, (h, o) -> h.put(h.size(), o), (h, o) -> {}) // Create a map of the index to the object .forEach((i, o) -> { // Now we can use a BiConsumer forEach! System.out.println(String.format("%d => %s", i, o)); }); Output: 0 => First 1 => Second 2 => Third 3 => Fourth 4 => Fifth
If you happen to use Vavr(formerly known as Javaslang), you can leverage the dedicated method: Stream.of("A", "B", "C") .zipWithIndex(); If we print out the content, we will see something interesting: Stream((A, 0), ?) This is because Streams are lazy and we have no clue about next items in the stream.
Here is code by abacus-common Stream.of(names).indexed() .filter(e -> e.value().length() <= e.index()) .map(Indexed::value).toList(); Disclosure: I'm the developer of abacus-common.
There isn't a way to iterate over a Stream whilst having access to the index because a Stream is unlike any Collection. A Stream is merely a pipeline for carrying data from one place to another, as stated in the documentation: No storage. A stream is not a data structure that stores elements; instead, they carry values from a source (which could be a data structure, a generator, an IO channel, etc) through a pipeline of computational operations. Of course, as you appear to be hinting at in your question, you could always convert your Stream<V> to a Collection<V>, such as a List<V>, in which you will have access to the indexes.
With https://github.com/poetix/protonpack u can do that zip: String[] names = {"Sam","Pamela", "Dave", "Pascal", "Erik"}; List<String> nameList; Stream<Integer> indices = IntStream.range(0, names.length).boxed(); nameList = StreamUtils.zip(indices, stream(names),SimpleEntry::new) .filter(e -> e.getValue().length() <= e.getKey()).map(Entry::getValue).collect(toList()); System.out.println(nameList);
If you don't mind using a third-party library, Eclipse Collections has zipWithIndex and forEachWithIndex available for use across many types. Here's a set of solutions to this challenge for both JDK types and Eclipse Collections types using zipWithIndex. String[] names = { "Sam", "Pamela", "Dave", "Pascal", "Erik" }; ImmutableList<String> expected = Lists.immutable.with("Erik"); Predicate<Pair<String, Integer>> predicate = pair -> pair.getOne().length() <= pair.getTwo() + 1; // JDK Types List<String> strings1 = ArrayIterate.zipWithIndex(names) .collectIf(predicate, Pair::getOne); Assert.assertEquals(expected, strings1); List<String> list = Arrays.asList(names); List<String> strings2 = ListAdapter.adapt(list) .zipWithIndex() .collectIf(predicate, Pair::getOne); Assert.assertEquals(expected, strings2); // Eclipse Collections types MutableList<String> mutableNames = Lists.mutable.with(names); MutableList<String> strings3 = mutableNames.zipWithIndex() .collectIf(predicate, Pair::getOne); Assert.assertEquals(expected, strings3); ImmutableList<String> immutableNames = Lists.immutable.with(names); ImmutableList<String> strings4 = immutableNames.zipWithIndex() .collectIf(predicate, Pair::getOne); Assert.assertEquals(expected, strings4); MutableList<String> strings5 = mutableNames.asLazy() .zipWithIndex() .collectIf(predicate, Pair::getOne, Lists.mutable.empty()); Assert.assertEquals(expected, strings5); Here's a solution using forEachWithIndex instead. MutableList<String> mutableNames = Lists.mutable.with("Sam", "Pamela", "Dave", "Pascal", "Erik"); ImmutableList<String> expected = Lists.immutable.with("Erik"); List<String> actual = Lists.mutable.empty(); mutableNames.forEachWithIndex((name, index) -> { if (name.length() <= index + 1) actual.add(name); }); Assert.assertEquals(expected, actual); If you change the lambdas to anonymous inner classes above, then all of these code examples will work in Java 5 - 7 as well. Note: I am a committer for Eclipse Collections
You can use IntStream.iterate() to get the index: String[] names = {"Sam","Pamela", "Dave", "Pascal", "Erik"}; List<String> nameList = IntStream.iterate(0, i -> i < names.length, i -> i + 1) .filter(i -> names[i].length() <= i) .mapToObj(i -> names[i]) .collect(Collectors.toList()); This only works for Java 9 upwards in Java 8 you can use this: String[] names = {"Sam","Pamela", "Dave", "Pascal", "Erik"}; List<String> nameList = IntStream.iterate(0, i -> i + 1) .limit(names.length) .filter(i -> names[i].length() <= i) .mapToObj(i -> names[i]) .collect(Collectors.toList());
If you are trying to get an index based on a predicate, try this: If you only care about the first index: OptionalInt index = IntStream.range(0, list.size()) .filter(i -> list.get(i) == 3) .findFirst(); Or if you want to find multiple indexes: IntStream.range(0, list.size()) .filter(i -> list.get(i) == 3) .collect(Collectors.toList()); Add .orElse(-1); in case you want to return a value if it doesn't find it.
One possible way is to index each element on the flow: AtomicInteger index = new AtomicInteger(); Stream.of(names) .map(e->new Object() { String n=e; public i=index.getAndIncrement(); }) .filter(o->o.n.length()<=o.i) // or do whatever you want with pairs... .forEach(o->System.out.println("idx:"+o.i+" nam:"+o.n)); Using an anonymous class along a stream is not well-used while being very useful.
If you need the index in the forEach then this provides a way. public class IndexedValue { private final int index; private final Object value; public IndexedValue(final int index, final Object value) { this.index = index; this.value = value; } public int getIndex() { return index; } public Object getValue() { return value; } } Then use it as follows. #Test public void withIndex() { final List<String> list = Arrays.asList("a", "b"); IntStream.range(0, list.size()) .mapToObj(index -> new IndexedValue(index, list.get(index))) .forEach(indexValue -> { System.out.println(String.format("%d, %s", indexValue.getIndex(), indexValue.getValue().toString())); }); }
you don't need a map necessarily that is the closest lambda to the LINQ example: int[] idx = new int[] { 0 }; Stream.of(names) .filter(name -> name.length() <= idx[0]++) .collect(Collectors.toList());
You can create a static inner class to encapsulate the indexer as I needed to do in example below: static class Indexer { int i = 0; } public static String getRegex() { EnumSet<MeasureUnit> range = EnumSet.allOf(MeasureUnit.class); StringBuilder sb = new StringBuilder(); Indexer indexer = new Indexer(); range.stream().forEach( measureUnit -> { sb.append(measureUnit.acronym); if (indexer.i < range.size() - 1) sb.append("|"); indexer.i++; } ); return sb.toString(); }
This question (Stream Way to get index of first element matching boolean) has marked the current question as a duplicate, so I can not answer it there; I am answering it here. Here is a generic solution to get the matching index that does not require an external library. If you have a list. public static <T> int indexOf(List<T> items, Predicate<T> matches) { return IntStream.range(0, items.size()) .filter(index -> matches.test(items.get(index))) .findFirst().orElse(-1); } And call it like this: int index = indexOf(myList, item->item.getId()==100); And if using a collection, try this one. public static <T> int indexOf(Collection<T> items, Predicate<T> matches) { int index = -1; Iterator<T> it = items.iterator(); while (it.hasNext()) { index++; if (matches.test(it.next())) { return index; } } return -1; }
String[] namesArray = {"Sam","Pamela", "Dave", "Pascal", "Erik"}; String completeString = IntStream.range(0,namesArray.length) .mapToObj(i -> namesArray[i]) // Converting each array element into Object .map(String::valueOf) // Converting object to String again .collect(Collectors.joining(",")); // getting a Concat String of all values System.out.println(completeString); OUTPUT : Sam,Pamela,Dave,Pascal,Erik String[] namesArray = {"Sam","Pamela", "Dave", "Pascal", "Erik"}; IntStream.range(0,namesArray.length) .mapToObj(i -> namesArray[i]) // Converting each array element into Object .map(String::valueOf) // Converting object to String again .forEach(s -> { //You can do various operation on each element here System.out.println(s); }); // getting a Concat String of all To Collect in the List: String[] namesArray = {"Sam","Pamela", "Dave", "Pascal", "Erik"}; List<String> namesList = IntStream.range(0,namesArray.length) .mapToObj(i -> namesArray[i]) // Converting each array element into Object .map(String::valueOf) // Converting object to String again .collect(Collectors.toList()); // collecting elements in List System.out.println(listWithIndex);
As jean-baptiste-yunès said, if your stream is based on a java List then using an AtomicInteger and its incrementAndGet method is a very good solution to the problem and the returned integer does correspond to the index in the original List as long as you do not use a parallel stream.
Here's solution for standard Java: In-line solution: Arrays.stream("zero,one,two,three,four".split(",")) .map(new Function<String, Map.Entry<Integer, String>>() { int index; #Override public Map.Entry<Integer, String> apply(String s) { return Map.entry(index++, s); } }) .forEach(System.out::println); and more readable solution with utility method: static <T> Function<T, Map.Entry<Integer, T>> mapWithIntIndex() { return new Function<T, Map.Entry<Integer, T>>() { int index; #Override public Map.Entry<Integer, T> apply(T t) { return Map.entry(index++, t); } }; } ... Arrays.stream("zero,one,two,three,four".split(",")) .map(mapWithIntIndex()) .forEach(System.out::println);
If the list is unique, we can make use of indexOf method. List<String> names = Arrays.asList("Sam", "Pamela", "Dave", "Pascal", "Erik"); names.forEach(name ->{ System.out.println((names.indexOf(name) + 1) + ": " + name); });
Size-limited queue that holds last N elements in Java
A very simple & quick question on Java libraries: is there a ready-made class that implements a Queue with a fixed maximum size - i.e. it always allows addition of elements, but it will silently remove head elements to accomodate space for newly added elements. Of course, it's trivial to implement it manually: import java.util.LinkedList; public class LimitedQueue<E> extends LinkedList<E> { private int limit; public LimitedQueue(int limit) { this.limit = limit; } #Override public boolean add(E o) { super.add(o); while (size() > limit) { super.remove(); } return true; } } As far as I see, there's no standard implementation in Java stdlibs, but may be there's one in Apache Commons or something like that?
Apache commons collections 4 has a CircularFifoQueue<> which is what you are looking for. Quoting the javadoc: CircularFifoQueue is a first-in first-out queue with a fixed size that replaces its oldest element if full. import java.util.Queue; import org.apache.commons.collections4.queue.CircularFifoQueue; Queue<Integer> fifo = new CircularFifoQueue<Integer>(2); fifo.add(1); fifo.add(2); fifo.add(3); System.out.println(fifo); // Observe the result: // [2, 3] If you are using an older version of the Apache commons collections (3.x), you can use the CircularFifoBuffer which is basically the same thing without generics. Update: updated answer following release of commons collections version 4 that supports generics.
Guava now has an EvictingQueue, a non-blocking queue which automatically evicts elements from the head of the queue when attempting to add new elements onto the queue and it is full. import java.util.Queue; import com.google.common.collect.EvictingQueue; Queue<Integer> fifo = EvictingQueue.create(2); fifo.add(1); fifo.add(2); fifo.add(3); System.out.println(fifo); // Observe the result: // [2, 3]
I like #FractalizeR solution. But I would in addition keep and return the value from super.add(o)! public class LimitedQueue<E> extends LinkedList<E> { private int limit; public LimitedQueue(int limit) { this.limit = limit; } #Override public boolean add(E o) { boolean added = super.add(o); while (added && size() > limit) { super.remove(); } return added; } }
Use composition not extends (yes I mean extends, as in a reference to the extends keyword in java and yes this is inheritance). Composition is superier because it completely shields your implementation, allowing you to change the implementation without impacting the users of your class. I recommend trying something like this (I'm typing directly into this window, so buyer beware of syntax errors): public LimitedSizeQueue implements Queue { private int maxSize; private LinkedList storageArea; public LimitedSizeQueue(final int maxSize) { this.maxSize = maxSize; storageArea = new LinkedList(); } public boolean offer(ElementType element) { if (storageArea.size() < maxSize) { storageArea.addFirst(element); } else { ... remove last element; storageArea.addFirst(element); } } ... the rest of this class A better option (based on the answer by Asaf) might be to wrap the Apache Collections CircularFifoBuffer with a generic class. For example: public LimitedSizeQueue<ElementType> implements Queue<ElementType> { private int maxSize; private CircularFifoBuffer storageArea; public LimitedSizeQueue(final int maxSize) { if (maxSize > 0) { this.maxSize = maxSize; storateArea = new CircularFifoBuffer(maxSize); } else { throw new IllegalArgumentException("blah blah blah"); } } ... implement the Queue interface using the CircularFifoBuffer class }
The only thing I know that has limited space is the BlockingQueue interface (which is e.g. implemented by the ArrayBlockingQueue class) - but they do not remove the first element if filled, but instead block the put operation until space is free (removed by other thread). To my knowledge your trivial implementation is the easiest way to get such an behaviour.
You can use a MinMaxPriorityQueue from Google Guava, from the javadoc: A min-max priority queue can be configured with a maximum size. If so, each time the size of the queue exceeds that value, the queue automatically removes its greatest element according to its comparator (which might be the element that was just added). This is different from conventional bounded queues, which either block or reject new elements when full.
An LRUMap is another possibility, also from Apache Commons. http://commons.apache.org/collections/apidocs/org/apache/commons/collections/map/LRUMap.html
Ok I'll share this option. This is a pretty performant option - it uses an array internally - and reuses entries. It's thread safe - and you can retrieve the contents as a List. static class FixedSizeCircularReference<T> { T[] entries FixedSizeCircularReference(int size) { this.entries = new Object[size] as T[] this.size = size } int cur = 0 int size synchronized void add(T entry) { entries[cur++] = entry if (cur >= size) { cur = 0 } } List<T> asList() { int c = cur int s = size T[] e = entries.collect() as T[] List<T> list = new ArrayList<>() int oldest = (c == s - 1) ? 0 : c for (int i = 0; i < e.length; i++) { def entry = e[oldest + i < s ? oldest + i : oldest + i - s] if (entry) list.add(entry) } return list } }
public class ArrayLimitedQueue<E> extends ArrayDeque<E> { private int limit; public ArrayLimitedQueue(int limit) { super(limit + 1); this.limit = limit; } #Override public boolean add(E o) { boolean added = super.add(o); while (added && size() > limit) { super.remove(); } return added; } #Override public void addLast(E e) { super.addLast(e); while (size() > limit) { super.removeLast(); } } #Override public boolean offerLast(E e) { boolean added = super.offerLast(e); while (added && size() > limit) { super.pollLast(); } return added; } }
How to create a decent toString() method in scala using reflection?
To make debug-time introspection into classes easy, I'd like to make a generic toString method in the base class for the objects in question. As it's not performance critical code, I'd like to use Reflection to print out field name/value pairs ("x=1, y=2" etc). Is there an easy way to do this? I tried several potential solutions, and ran up against security access issues, etc. To be clear, the toString() method in the base class should reflectively iterate over public vals in any classes that inherit from it, as well as any traits that are mixed in.
Example: override def toString() = { getClass().getDeclaredFields().map { field:Field => field.setAccessible(true) field.getName() + ": " + field.getType() + " = " + field.get(this).toString() }.deepMkString("\n") } Uses Java Reflection API, so don't forget to import java.lang.reflect._ Also, you may need to catch IllegalAccessException on the field.get(this) calls in some scenarios, but this is just meant as a starting point.
Are you aware the Scala case classes get these compiler-generated methods: toString(): String equals(other: Any): Boolean hashCode: Int They also get companion objects for "new-less" constructors and pattern matching. The generated toString() is pretty much like the one you describe.
import util._ // For Scala 2.8.x NameTransformer import scala.tools.nsc.util._ // For Scala 2.7.x NameTransformer /** * Repeatedly run `f` until it returns None, and assemble results in a Stream. */ def unfold[A](a: A, f: A => Option[A]): Stream[A] = { Stream.cons(a, f(a).map(unfold(_, f)).getOrElse(Stream.empty)) } def get[T](f: java.lang.reflect.Field, a: AnyRef): T = { f.setAccessible(true) f.get(a).asInstanceOf[T] } /** * #return None if t is null, Some(t) otherwise. */ def optNull[T <: AnyRef](t: T): Option[T] = if (t eq null) None else Some(t) /** * #return a Stream starting with the class c and continuing with its superclasses. */ def classAndSuperClasses(c: Class[_]): Stream[Class[_]] = unfold[Class[_]](c, (c) => optNull(c.getSuperclass)) def showReflect(a: AnyRef): String = { val fields = classAndSuperClasses(a.getClass).flatMap(_.getDeclaredFields).filter(!_.isSynthetic) fields.map((f) => NameTransformer.decode(f.getName) + "=" + get(f, a)).mkString(",") } // TEST trait T { val t1 = "t1" } class Base(val foo: String, val ?? : Int) { } class Derived(val d: Int) extends Base("foo", 1) with T assert(showReflect(new Derived(1)) == "t1=t1,d=1,??=1,foo=foo")
Scala doesn't generate any public fields. They're all going to be private. The accessor methods are what will be public, reflect upon those. Given a class like: class A { var x = 5 } The generated bytecode looks like: private int x; public void x_$eq(int); public int x();