私は、関数で引数や結果からジェネリック型をリンクしたいと思います。ここでは簡単な例です:
private void take(final Function<ListIterator<?>, ?> takeFunction) {
final ListIterator<String> stringItr = new ArrayList<String>().listIterator();
final ListIterator<Integer> intItr = new ArrayList<Integer>().listIterator();
final String string = (String) takeFunction.apply(stringItr);
final Integer integer = (Integer) takeFunction.apply(intItr);
}
take(itr -> itr.next());
take(itr -> itr.previous());
私の関数が返すがリストに何であることは明らかであるので、私はキャストを行うにはしたくありません。私はこのような何かを書きたいと思います:
private void take(final Function<ListIterator<T>, T> takeFunction) {
final ListIterator<String> stringItr = new ArrayList<String>().listIterator();
final ListIterator<Integer> intItr = new ArrayList<Integer>().listIterator();
final String string = takeFunction.apply(stringItr);
final Integer integer = takeFunction.apply(intItr);
}
それを達成する方法はありますか?
前もって感謝します
編集:一部の人々は、より実際のコードを尋ねました。私は、リストのリストのイテレータを作成しようが、私は私のサブリストは、必要時にのみロードされたいです。私は、一般的な方法は、自分自身の反復子::次および前で呼ばれるようにしたいと思います。
ここではより具体的なコードは次のとおりです。
List<List<String>> lists;
ListIterator<List<String>> curListsIter;
ListIterator<String> curStringIter;
@Override
public String next() {
return get(
listIterator -> listIterator.hasNext(),
listIterator -> listIterator.next(),
list -> list.listIterator());
}
@Override
public String previous() {
return get(
listIterator -> listIterator.hasPrevious(),
listIterator -> listIterator.previous(),
list -> list.listIterator(list.size()));
}
private String get(final Function<ListIterator<?>, Boolean> has,
final Function<ListIterator<?>, ?> item,
final Function<List<String>, ListIterator<String>> iterator) {
// The current sub list has an item to get
if (has.apply(curStringIter)) {
return (String) item.apply(curStringIter);
}
// There is a list in the direction
else if (has.apply(curListsIter)) {
curStringIter = iterator.apply(
(List<String>) item.apply(curListsIter));
return get(has, item, iterator);
}
// No more item in sub list nor list
else {
throw new NoSuchElementException();
}
}
潜在的にこのコードコンパイルとは動作しますが、私は(「文字列」と「リスト」への)getメソッドの両方のキャストせずにそれを行うしたいと思います。
踏まえ、この答えは、あなたはこのようなあなたの実際の問題を解決することができます:
public class Example {
List<List<String>> lists;
ListIterator<List<String>> curListsIter;
ListIterator<String> curStringIter;
@Override
public String next() {
return get(ListIterator::hasNext, ListIterator::next, List::listIterator);
}
@Override
public String previous() {
return get(ListIterator::hasPrevious, ListIterator::previous, Example::atEnd);
}
private static <T> ListIterator<T> atEnd(List<T> list) {
return list.listIterator(list.size());
}
interface IterFunction {
<T> T apply(ListIterator<T> t);
}
interface GetIterFunction {
<T> ListIterator<T> apply(List<T> t);
}
private String get(Predicate<ListIterator<?>> has,
IterFunction item, GetIterFunction getIter) {
if(curListsIter == null) curListsIter = getIter.apply(lists);
while(curStringIter == null || !has.test(curStringIter)) {
// may throw NoSuchElementException
curStringIter = getIter.apply(item.apply(curListsIter));
}
return item.apply(curStringIter);
}
}
それらの型の変数を宣言するための構文はありませんようジェネリック関数法との機能的なインタフェースは、ラムダ式を経て実現し得ることができません。しかし、彼らはほとんどの機能は、単に既存のメソッドを呼び出しますよう、ここでは簡単ですメソッド参照、を介して実施することができます。
唯一のリストの末尾を指すイテレータリストを取得することは、我々は、ここに新しいものを作成する必要が理由です既存の方法、単一の呼び出しとして表現できませんatEnd
方法を。これは、コンパイラは、合成方法ラムダの体を保持し、それへのメソッド参照を作成を生成する、フードの下ラムダ式のために何をするかは基本的であることに注意してください。手動でメソッドを宣言するときしかし、私たちは、ラムダ式とは異なり、それは一般的なことができます。