This question is just for fun.
I have this method:
private static String getBaseDomain(String fullDomain) {
// we take the base domain from the usual xxx.yyy.basedomain.tld: we
// want only the last 2 elements: basedomain.tld
List<String> elements = Arrays.asList(fullDomain.split("\\."));
if( elements.size() > 2){
elements = elements.subList(elements.size()-2, elements.size());
}
return String.join(".", elements);
}
And I'm wondering how to get the same result using the java stream API (actually, I'm wondering which method would be the most resource-efficient).
I can't figure how to get only the last 2 elements from a stream: limit(2)
will give me the first two, and for skip(XXX)
I don't know how to extract the size of the stream "inline".
Can you tell me how you would do?
You could use skip
:
elements.stream().skip(elements.size() - 2)
From the API:
Returns a stream consisting of the remaining elements of this stream after discarding the first n elements of the stream. If this stream contains fewer than n elements then an empty stream will be returned.
Probably useless example:
// a list made of a, b, c and d
List<String> l = Arrays.asList("a", "b", "c", "d");
// prints c and d
l.stream().skip(l.size() - 2).forEach(System.out::println);
Probably useless note:
As mentioned by a few, this only works if you have a size to work with, i.e. if you're streaming from a collection.
Quoting Nicolas, a stream doesn't have a size.
You could do a bit of inlining of your original approach, which I think shortens it up nicely, and you don't even have to use a stream:
String[] a = fullDomain.split("\\.");
return String.join(".", Arrays.asList(a)
.subList(Math.max(0, a.length-2), a.length));
If you really want to use a stream, you can use the array-subrange stream source:
String[] a = fullDomain.split("\\.");
return Arrays.stream(a, Math.max(0, a.length-2), a.length)
.collect(Collectors.joining("."));
If all you have is a stream, whose size you don't have in advance, I'd just dump the elements into an ArrayDeque
:
final int N = 2;
Stream<String> str = ... ;
Deque<String> deque = new ArrayDeque<>(N);
str.forEachOrdered(s -> {
if (deque.size() == N) deque.removeFirst();
deque.addLast(s);
});
return String.join(".", deque);
Of course, this isn't as general as writing a collector, but for simple cases it's probably just fine.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With