我正在尝试学习使用Stream API的细节,我给自己的一个任务是尝试编写一个无限的方法DoubleStream并尝试计算总和(假设它收敛).也就是说,我想写一个方法
public static double infiniteSum(DoubleStream ds) { ... }
Run Code Online (Sandbox Code Playgroud)
我可以用类似的东西打电话
double sum = infiniteSum(IntStream.iterate(1, (i -> i + 1))
.mapToDouble(n -> 1 / ((double)n * n)));
Run Code Online (Sandbox Code Playgroud)
得到的总和(1 + 1/2 2 + 1/3 2 + ...)=ζ(2)=π 2 /6号
我粗略的方法这样做的方式:
public static void yeOldeWaye() {
double sum = 0;
for (double n = 1; ; n++) {
double term = 1 / (n * n);
if (Math.abs(term) <= 1e-12 * Math.abs(sum)) {
break;
}
sum += term;
}
System.out.println(sum); …Run Code Online (Sandbox Code Playgroud) 如何用新的Java Stream API替换此代码:
int n = someFunction(); // n > 0
for (int i = 3; i * i <= n; i += 2)
System.out.print(i);
Run Code Online (Sandbox Code Playgroud)
我试过用IntStream.iterate(3, i -> i + 2),但我不能添加停止条件.
据我所知,我不能.limit(int)在这里使用方法.
有任何想法吗?
我已经看到takeWhile了 Java 8 流 API 的一些实现,但它们似乎都将流转换为非并行流。例如这个:
static <T> Spliterator<T> takeWhile(
Spliterator<T> splitr, Predicate<? super T> predicate) {
return new Spliterators.AbstractSpliterator<T>(splitr.estimateSize(), 0) {
boolean stillGoing = true;
@Override public boolean tryAdvance(Consumer<? super T> consumer) {
if (stillGoing) {
boolean hadNext = splitr.tryAdvance(elem -> {
if (predicate.test(elem)) {
consumer.accept(elem);
} else {
stillGoing = false;
}
});
return hadNext && stillGoing;
}
return false;
}
};
}
static <T> Stream<T> takeWhile(Stream<T> stream, Predicate<? super T> predicate) {
return …Run Code Online (Sandbox Code Playgroud) 我正在尝试从特定实例类型的顶级异常中递归地找到所有内部异常(getCause的)。
public class MyCustomRunTimeException extends RuntimeException {
public MyCustomRunTimeException() {
}
public MyCustomRunTimeException(Exception innerException) {
super(innerException);
}
}
Run Code Online (Sandbox Code Playgroud)
这是我尝试过的:
和我早期的“查找”方法:
private void findAllSpecificTypeOfInnerExceptions(Exception ex)
{
Collection<MyCustomRunTimeException> MyCustomRunTimeExceptions = Stream.iterate(ex, Throwable::getCause)
.filter(element ->
element != null
&& element instanceof MyCustomRunTimeException
)
.map(obj -> (MyCustomRunTimeException) obj)
.collect(Collectors.toList());
}
Run Code Online (Sandbox Code Playgroud)
它不起作用。:(我已经尝试了其他几件事(尚未显示)...如果我收到的任何内容都不会引发异常,则会将它们发布为“追加”到这个问题。获取NullPointers异常,以及(取决于我的调整)java.lang.reflect.InvocationTargetException异常。
这是一些可以找到1:N“匹配”的示例。
Exception exampleOne = new MyCustomRunTimeException();
Exception exampleTwo = new Exception(new MyCustomRunTimeException());
Exception exampleThree =new Exception(new Exception(new MyCustomRunTimeException()));
Exception exampleFour =new Exception(new Exception(new MyCustomRunTimeException(new ArithmeticException())));
Run Code Online (Sandbox Code Playgroud) 如果我有一个List包含对象
new MyObj("some"),
new MyObj("foo"),
new MyObj("bar"),
new MyObj("xyz");
Run Code Online (Sandbox Code Playgroud)
并希望在匹配某些条件后使用Java 8流对其进行过滤,例如
myObj.prop = "foo";
Run Code Online (Sandbox Code Playgroud)
如何实现?
以上示例的结果应为
new MyObj("some"),
new MyObj("foo")
Run Code Online (Sandbox Code Playgroud)
那将是“传统”的方式:
List<MyObj> results = new ArrayList<>();
for (MyObj myObj : myObjList) {
if (!myObj.prop.equals("foo")) {
results.add(myObj);
} else {
results.add(myObj);
break;
}
}
Run Code Online (Sandbox Code Playgroud)
它不是谓词限制流的重复,因为它不包含匹配的元素。但是,我应该能够适应takeWhile操作。
Java 8.
至少对我来说,将forEach循环转换为lambda表达式是可以理解的.另一方面,转换基于条件的for循环不是.
如果可能,我的问题是:如何将以下for循环转换为lambda表达式
List<Field> fields = new LinkedList<>();
for (Class<?> c = this.getClass(); c != null; c = c.getSuperclass())
Collections.addAll(fields, c.getDeclaredFields());
Run Code Online (Sandbox Code Playgroud)
提前谢谢了,
〜本.
在网络中,我发现只有一种方法可以停止迭代方法.通过使用limit()函数.但是,这会迭代一个混合的循环.我想用来停止一个谓词.
...
Stream.iterate(0, i -> i*2).while(i -> i < MAX)
...
Run Code Online (Sandbox Code Playgroud)
有没有办法用Streams做到这一点?
更新1:使用Java 8
我想迭代/生成一个无限的 IntStream 或 LongStream 并通过提供的最大值来限制它们,而不是通过操作可能的元素计数limit(long n),例如获得前 20 个正偶数:
List<Integer> evens = IntStream.iterate(0, i -> i + 2)
.limit(20)
.boxed()
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
我需要的是通过最大值限制流。例如,如果我需要 1000 以下的所有 2 次幂
List<Integer> evens = IntStream.iterate(1, i -> i * 2) //1, 2, 4, 8, 16, 32...
.limit(<here some how use the value 1000>)
.boxed()
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
或斐波那契数列
List<Long> fibs = Stream.iterate(new long[]{1,1}, f -> new long[]{f[1], f[0] + f[1]}) //1,1,2,3,5,8,13,21...
.mapToLong(f -> f[1])
.limit(i -> i < 1000) //I know this doesn't work as limit …Run Code Online (Sandbox Code Playgroud) 我正在慢慢学习Java 8的新功能,并试图找到一种以流方式处理类层次结构(从子级到父级)的方法。
例如,在类或其父级上找到注释。
在Java 8之前,我会这样完成:
public static <T extends Annotation> T getAnnonationOn(Class<?> type, Class<T> annType) {
Class<?> t = type;
T annot = null;
while (t != null && annot == null) {
annot = t.getAnnotation(annType);
t = t.getSuperclass();
}
return annot;
}
Run Code Online (Sandbox Code Playgroud)
现在,我希望以一种更加“功能性的编程”方式来做到这一点。我找不到比使用以下递归连接流更好的方法:
import java.lang.annotation.Annotation;
import java.util.stream.Stream;
public static <T extends Annotation> T getAnnonationOn(Class<?> type, Class<T> annType) {
return ClassIterator.streamSuperclass(type)
.map(t -> t.getAnnotation(annType))
.filter(a -> a != null)
.findFirst()
.orElse(null);
}
public static class ClassIterator {
public static Stream<Class<?>> …Run Code Online (Sandbox Code Playgroud) 我想从流中收集前n个元素,而不是遍历整个事物.是否有标准方法可以做到这一点?翼
MyList.stream()
.filter(x -> predicate(x))
.findFirstN(100)
Run Code Online (Sandbox Code Playgroud)
会从流中返回最多100个元素的集合吗?我的另一种方法是评估整个流,然后从结果中进行采样,但这并没有利用流固有的惰性评估.