Bir harita fonksiyonuna ihtiyacım var . Java'da zaten böyle bir şey var mı?
(Merak edenler için: Elbette bu önemsiz işlevi kendim nasıl uygulayacağımı biliyorum ...)
Bir harita fonksiyonuna ihtiyacım var . Java'da zaten böyle bir şey var mı?
(Merak edenler için: Elbette bu önemsiz işlevi kendim nasıl uygulayacağımı biliyorum ...)
Yanıtlar:
Java 6'dan itibaren JDK'da bir işlev fikri yoktur.
Guava'da bir İşlev arayüzü var ve
yöntem ihtiyacınız olan işlevselliği sağlıyor.
Collections2.transform(Collection<E>, Function<E,E2>)
Misal:
// example, converts a collection of integers to their
// hexadecimal string representations
final Collection<Integer> input = Arrays.asList(10, 20, 30, 40, 50);
final Collection<String> output =
Collections2.transform(input, new Function<Integer, String>(){
@Override
public String apply(final Integer input){
return Integer.toHexString(input.intValue());
}
});
System.out.println(output);
Çıktı:
[a, 14, 1e, 28, 32]
Bu günlerde, Java 8 ile aslında bir harita işlevi var, bu yüzden muhtemelen kodu daha özlü bir şekilde yazardım:
Collection<String> hex = input.stream()
.map(Integer::toHexString)
.collect(Collectors::toList);
Collections2.transform(input -> Integer.toHexString(intput.intValue())
Java 8'den beri, bunu JDK'da yapmak için bazı standart seçenekler vardır:
Collection<E> in = ...
Object[] mapped = in.stream().map(e -> doMap(e)).toArray();
// or
List<E> mapped = in.stream().map(e -> doMap(e)).collect(Collectors.toList());
Bkz java.util.Collection.stream()
ve java.util.stream.Collectors.toList()
.
toList()
. Farklı tipe değiştirme:(List<R>)((List) list).replaceAll(o -> doMap((E) o));
e -> doMap(e)
ile değiştirilebilir doMap
?
foo::doMap
ya da benzeri bir şey Foo::doMap
.
Java'nın sahip olmasını istediğiniz şeylerin çoğunu işleyen Fonksiyonel Java adlı harika bir kütüphane var ama öyle değil. Sonra tekrar, Java'nın yapması gereken her şeyi yapan ama yine de JVM için yazılmış bir şeyle uyumlu olmayan bu harika dil Scala da var.
a.map({int i => i + 42});
derleyiciyi genişlettiler mi? veya önişlemci eklediniz mi?
Collections2.transform()
Guava'dan çok dikkatli olun . Bu yöntemin en büyük avantajı aynı zamanda en büyük tehlikesidir: tembellik.
Aşağıdakiler için de Lists.transform()
geçerli olduğuna inandığım belgelere bakın Collections2.transform()
:
İşlev tembel olarak uygulanır, gerektiğinde çağrılır. Bu, döndürülen listenin bir görünüm olması için gereklidir, ancak bu, List.contains (java.lang.Object) ve List.hashCode () gibi toplu işlemler için işlevin birçok kez uygulanacağı anlamına gelir. Bunun iyi çalışması için işlev hızlı olmalıdır. Döndürülen listenin bir görünüm olması gerekmediğinde tembel değerlendirmeyi önlemek için, döndürülen listeyi seçtiğiniz yeni bir listeye kopyalayın.
Ayrıca belgelerinde Collections2.transform()
canlı bir görünüm aldığınızı belirtiyorlar, kaynak listesindeki bu değişiklik dönüştürülmüş listeyi etkiliyor. Bu tür davranışlar, geliştirici çalışma şeklini fark etmezse izlemesi zor sorunlara yol açabilir.
Daha klasik bir "harita" istiyorsanız, bu sadece bir kez ve bir kez çalışır, o zaman FluentIterable
çok daha basit bir operasyonu olan Guava'dan daha iyi durumdasınız. İşte bunun için google örneği:
FluentIterable
.from(database.getClientList())
.filter(activeInLastMonth())
.transform(Functions.toStringFunction())
.limit(10)
.toList();
transform()
İşte harita yöntemi. İle aynı İşlev <> "geri aramalar" kullanır Collections.transform()
. Geri aldığınız liste salt okunurdur, copyInto()
okuma-yazma listesi almak için kullanın .
Aksi takdirde java8 lambdalarla ortaya çıktığında, bu eski olacak.
Bu, haritayı kullanabileceğiniz başka bir işlevsel lib: http://code.google.com/p/totallylazy/
sequence(1, 2).map(toString); // lazily returns "1", "2"
Eski bir soru olmasına rağmen başka bir çözüm göstermek istiyorum:
Java jeneriklerini ve java 8 akışlarını kullanarak kendi işleminizi tanımlamanız yeterlidir:
public static <S, T> List<T> map(Collection<S> collection, Function<S, T> mapFunction) {
return collection.stream().map(mapFunction).collect(Collectors.toList());
}
Bundan böyle kod yazabilirsiniz:
List<String> hex = map(Arrays.asList(10, 20, 30, 40, 50), Integer::toHexString);