public static <A, B> List<B> map(
List<? extends A> xs,
Func1<? super A, ? extends B> transformer
) {
List<B> ys = new ArrayList<B>();
map(xy, transformer, ys);
return ys;
}
public static <A, B> Set<B> map(
Set<? extends A> xs,
Func1<? super A, ? extends B> transformer
) {
Set<B> ys = new HashSet<B>();
map(xy, transformer, ys);
return ys;
}
private static <A, B> map(
Collection<? extends A> xs,
Func1<? super A, ? extends B> transformer,
Iterable<B> ys
) {
for(A a : xs) {
ys.add(transformer.apply(a));
}
}
Работа выполнена.
Обратите внимание, что для API Java характерно передавать изменяемую коллекцию, а не создавать новую в методе. Лично я не фанат изменчивости на уровне коллекций, но это то, с чем мы должны работать (на Java).
(мне не нравятся A
и B
как общие параметры для такого рода вещей.)
Или вы можете использовать фабрику:
public static <A, B> List<B> map(
List<? extends A> xs,
Func1<? super A, ? extends B> transformer
) {
return map(xs, transformer, new CollectionFactory<B, List<B>>() {
public List<B> create() { return new ArrayList<B>(); }
});
}
public static <A, B> Set<B> map(
Set<? extends A> xs,
Func1<? super A, ? extends B> transformer
) {
return map(xs, transformer, new CollectionFactory<B, Set<B>>() {
public Set<B> create() { return new HashSet<B>(); }
});
}
private interface CollectionFactory<E, C extends Collection<E>> {
C create();
}
private static <A, B, C extends Collection<B>> C map(
Iterable<? extends A> xs,
Func1<? super A, ? extends B> transformer,
CollectionFactory<B, C> factory
) {
C ys = factory.create();
for(A a : xs) {
ys.add(transformer.apply(a));
}
return ys;
}
(Если вы можете мириться с бессмысленным многословием анонимных внутренних классов.)
Если бы не Collection
, вам нужно было бы вставить какой-нибудь (некрасивый) адаптер.
Для полноты (хотя и не проверенного, можно сделать с несколькими настройками), неприятное решение с использованием наследования:
Set<String> strs = hashSets().map(things, formatter);
...
public static <E> Functions<E, Set<E>> hashSets() {
return new Functions<E, Set<E>>() {
protected Set<E> createCollections() {
return new HashSet<E>();
}
};
}
public abstract class Functions<E, C extends Collection<E>> {
protected abstract C createCollection();
public <S> C map(
Set<? extends S> xs,
Func1<? super S, ? extends E> transformer
) {
C ys = createCollection();
for(S a : xs) {
ys.add(transformer.apply(a));
}
return ys;
}
public <S> C filter(
List<? extends S> xs,
Func1<? super S, Boolean> predicate // Predicate<? super S> might be nicer!!
) {
C ys = createCollection();
for(A a : xs) {
if(predicate.apply(a)) {
ys.add(a);
}
}
return ys;
}
}