可以使用番石榴轻松过滤列表或Iterables filter(Iterable<?> unfiltered, Class<T> type).此操作执行两个任务:列表被过滤并转换为给定类型T的序列.
然而,我常常最终Iterables<Something<?>>
得到Iterables<Something<T>>一些专门的T 的后续序列.
很明显,由于类型擦除,番石榴无法解决这个问题:Something<T>没有提供有关其T的任何直接信息.
可以说我有类似的东西S<? extends Number>.如果我能够定义一些谓词告诉我是否S<?>可以将其转换为S<Double>我可以将其用作文件管理器:
<T extends Number> Predicate<S<?>> isOfType(Class<N> type) {...}
Run Code Online (Sandbox Code Playgroud)
有:
Iterable<S<?>> numbers;
Iterable<S<?>> filtered = Iterable.filter(numbers, isOfType(Double.class));
Run Code Online (Sandbox Code Playgroud)
这执行过滤任务,但它错过了转换步骤.如果我认为我的Predicate运作良好,我甚至可以考虑转换:
Iterable<S<Double>> doubles = (Iterable<S<Double>>) filtered;
Run Code Online (Sandbox Code Playgroud)
但这暴露了一些丑陋的演员操作.
作为替代方案,我可以提供Function<S<?>, S<Double>>执行演员表演.Class.cast()但是,如果元素不能被转换(或转换),则它不应该抛出ClassCastException但只是返回null.这样可以在没有任何显式转换的情况下转换序列:
<T extends Number> Function<S<?>, S<T>> castOrNull(Class<N> type) {...}
Iterable<S<Double>> doubles = Iterable.filter(numbers, castOrNull(Double.class));
Run Code Online (Sandbox Code Playgroud)
但是列表并没有真正过滤:相反,它仍然包含无法转换或转换为每个元素的空对象S<Double>.但这可以通过额外的过滤步骤轻松解决,如:
Iterable<S<Double>> doubles = Iterables.filter(doubles, Predicates.notNull());
Run Code Online (Sandbox Code Playgroud)
第二种解决方案对我来说似乎更聪明.在 …
我在Windows上观察到Java7的通配符扩展行为的奇怪行为.
几个世纪以来,"*"与*之间存在着明显的差异.
似乎这对Java7来说不再适用(至少在Windows7上).
我在使用通配符类路径时注意到了这个问题.
尽管引用了wildcard-classpath,它仍然会被扩展.
因此,似乎不可能再将通配符传递给java应用程序.
因此使用java -cp "somewhere/*"将失败(如同"somewhere\*").
一种解决方法似乎是:java -cp "somewhere/*;"它抑制了扩张.
为了验证行为,我写了一个小的Echo.java类.
我发现使用java 1.6.0引用"*"和plain*就像预期的那样工作,而在Java7上我总是得到扩展的通配符.到目前为止,这在Windows7上被观察到,不知道XP上会发生什么.
问题出现了,因为Windows上的通配符永远不会被黑暗时代CMD.EXE扩展(就像UNIX上的任何shell一样).相反,每个可执行文件都必须使用setargv.obj显式执行此操作.
我发现了两个似乎描述类似问题的相关问题:
这是否被其他人观察到了?
或者是否有一些模糊的Windows或批处理文件设置来控制它?
迪特.
我尝试使用ForkJoinPool 来并行化我的CPU密集型计算.我对ForkJoinPool的理解是,只要任何任务可以执行,它就会继续工作.不幸的是,我经常观察工作线程空闲/等待,因此并非所有CPU都保持忙碌状态.有时我甚至观察到额外的工作线程.
我没想到这一点,因为我严格尝试使用非阻塞任务.我的观察非常类似于ForkJoinPool似乎浪费了一个线程.在对ForkJoinPool进行了大量调试之后我猜了一下:
我使用invokeAll()在子任务列表上分配工作.在invokeAll()完成后执行第一个任务本身,它开始加入其他任务.这很好,直到下一个要连接的任务位于执行队列之上.不幸的是,我提交了异步的其他任务而没有加入它们.我期望ForkJoin框架首先继续执行这些任务,然后再转回加入任何剩余的任务.
但它似乎不是这样工作的.相反,工作线程停止调用wait()直到等待的任务准备好(可能是由其他工作线程执行).我没有验证这一点,但似乎是调用join()的一般缺陷.
ForkJoinPool提供了一个asyncMode,但这是一个全局参数,不能用于单个提交.但我喜欢看到我的异步分叉任务很快就会被执行.
那么,为什么ForkJoinTask.doJoin()不是简单地在其队列之上执行任何可用任务,直到它准备好(由自己执行或被其他人窃取)?
新的番石榴10 可选状态是自然协变的,因此可以被铸造.
如果我这样做,它看起来有点难看:
Optional<Integer> opti = Optional.of(42);
Optional<Number> optn = (Optional) opti;
Run Code Online (Sandbox Code Playgroud)
我喜欢看到一些实用功能:
static <T> Optional<T> transform(Optional<? extends T> opt, Class<T> clazz);
Run Code Online (Sandbox Code Playgroud)
(如何将其表示为Optional的成员函数?)
甚至可以定义转换函数对象,如:
static <T> Function<Optional<? extends T>, Optional<T>>
transformer(Class<T> class);
Run Code Online (Sandbox Code Playgroud)
为了将a变换Collection<Optional<Double>>为a Collection<Optional<Number>>而不为每个创建新对象?
我认为即使返回的Function对象也可以通过内部单例来实现.
我经常使用供应商,现在我正在寻找新的Guava 10 Optional.
与供应商相比,可选保证永远不会返回null,而是抛出IllegalStateException.此外,它是不可变的,因此一旦创建它就具有固定的已知值.与此相反,可以使用供应商创建通过调用get()触发的不同或惰性值(但不强制执行此操作).
我跟着讨论为什么一个Optional不应该扩展供应商,我发现:
但我无法理解为什么,正如供应商明确指出的那样: 此接口不暗示任何保证.
对我来说它很合适,但似乎我过去常常以不同的方式雇用供应商.有人可以向我解释为什么不应该选择使用Optional作为供应商?
是的:将Optional转换为供应商非常容易(此外,您可以选择是否适应的Supplier.get()将返回Optional.get()或Optional.orNull()),但您需要进行一些额外的转换并拥有为每个创建新对象:-(
似乎供应商的预期用途与我对其文档的理解之间存在一些不匹配.
迪特.