这个问题只是为了好玩。
我有这个方法:
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);
}
我想知道如何使用java流API获得相同的结果(实际上,我想知道哪种方法最节省资源)。
我无法计算如何仅从流中获取最后2个元素:limit(2)
将为我提供第一个两个,而对于skip(XXX)
,我不会#39;知道如何提取流的大小&#34;内联&#34;。
你能告诉我你会怎么做吗?
答案 0 :(得分:5)
您可以使用skip
:
elements.stream().skip(elements.size() - 2)
来自API :
在丢弃流的前n个元素后,返回由此流的其余元素组成的流。如果此流包含少于n个元素,则将返回空流。
可能没用的例子:
// 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);
可能无用的说明:
正如少数人所提到的,只有当你有一个可以使用的尺寸时,这才有效,即如果你从一个集合中流式传输。
引用Nicolas,流没有大小。
答案 1 :(得分:2)
您可以对原始方法进行一些内联,我认为它可以很好地缩短它,您甚至不必使用流:
String[] a = fullDomain.split("\\.");
return String.join(".", Arrays.asList(a)
.subList(Math.max(0, a.length-2), a.length));
如果您真的想使用流,可以使用数组子范围流源:
String[] a = fullDomain.split("\\.");
return Arrays.stream(a, Math.max(0, a.length-2), a.length)
.collect(Collectors.joining("."));
如果你所拥有的只是一个你没有预先确定其大小的流,我只是将这些元素转储到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);
当然,这不像写一个收藏家那么笼统,但对于简单的情况,它可能就好了。
答案 2 :(得分:1)
如果elements
是一个流,您可以编写一个自定义收集器来保留最后K
个元素(可能还有这样的收集器):
List<?> lastK = ints.stream().collect(
Collector.of(
LinkedList::new,
(listA, el) -> {
listA.add(el);
if (listA.size() > K) {
listA.remove(0);
}
},
(listA, listB) -> {
while (listB.size() < K && !listA.isEmpty()) {
listB.addFirst(listA.removeLast());
}
return listB;
}));
答案 3 :(得分:1)
如果是索引集合,您可以使用
IntStream.range(elements.size() - 2, elements.size()).mapToObj(elements::get).forEach(System.out::print);