使用海藻石filter(Iterable<?> unfiltered, Class<T> type)
可以很容易地過濾清單或Iterables。此操作執行兩個任務:列表過濾和轉化爲給定類型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) {...}
有:
Iterable<S<?>> numbers;
Iterable<S<?>> filtered = Iterable.filter(numbers, isOfType(Double.class));
此進行過濾的任務,但它錯過了轉換步驟。 如果我認爲我的謂語行之有效我可能甚至想鑄造:
Iterable<S<Double>> doubles = (Iterable<S<Double>>) filtered;
但是,這暴露了一些醜陋的轉換操作。
作爲替代,我可以提供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));
但是是不是真的過濾列表:相反,它仍然包含了其不能轉換或強制轉換爲S<Double>
每個元素空的對象。 但是這可以通過附加的過濾步驟一樣容易解決:
Iterable<S<Double>> doubles = Iterables.filter(doubles, Predicates.notNull());
第二個解決辦法似乎要聰明得多給我。要定義的Function
可以執行強制轉換(隱藏未經檢查的操作),也可以根據需要創建一些新的對象S<T>
。
剩下的問題是: 有沒有更聰明的方法來執行必要的轉換和過濾一步?我可以簡單地定義像一些效用函數:
<I,O> Iterables<O> convert(
Iterables<O> input,
Function<? super I, ? extends O> convert,
Predicate<? super O> filter);
<I,O> Iterables<O> convert(
Iterables<O> input,
Function<? super I, ? extends O> convert);
當第二函數是第一個具有Predicates.notNull()
短切;
但值得擁有第一個函數,因爲謂詞不是必需的Predicates.notNull()
。想象一下Iterable<Iterable<? extends Number>>
。轉換函數Function<Iterable<? extends Number>, Iterable<Double>>
可能會簡單地返回一個可能爲空的過濾序列,而不是返回null。額外的過濾器最終可以使用Iterables.isEmpty()
刪除空序列。
如果'Iterable.filter(...)'返回一個具有擴展功能的迭代器,那麼你可以鏈式過濾器會很有用。 '/ * S extends Collection */Iterable
> doubles = Iterable.filter(numbers,castOrNull(Double.class))。filter(Predicates.notNull())。filter(Predicates.notEmpty());' – aalku想要一步到位呢?轉換和過濾是不同的操作。 – pawstrong