Eine ist eine andere Wahl hier für Java 6+
Schnittstellen:
interface TransformRule<In, Out> {
Out extract(In obj);
}
interface FilterRule<T> {
boolean apply(T obj);
}
Und Java8Stream artigen Container-Klasse für Ansammlung/Karte:
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
class FPMapContainer<KeyType, ValueType> extends FPContainer<Map<KeyType, ValueType>, Map.Entry<KeyType, ValueType>, ValueType> {
FPMapContainer(Map<KeyType, ValueType> container) {
super(container);
}
@Override
public <Out> FPMapContainer<KeyType, Out> map(TransformRule<Map.Entry<KeyType, ValueType>, Out> rule) {
return new FPMapContainer<>(handleContainer(getMapMapRule(rule)));
}
@Override
public FPMapContainer<KeyType, ValueType> filter(FilterRule<Map.Entry<KeyType, ValueType>> rule) {
return new FPMapContainer<>(handleContainer(getMapFilterRule(rule)));
}
@Override
public FPMapContainer<KeyType, ValueType> concat(Map<KeyType, ValueType> another) {
HashMap newOne = new HashMap(container);
newOne.putAll(another);
return new FPMapContainer<>(newOne);
}
@Override
public FPMapContainer<KeyType, ValueType> concat(FPContainer<Map<KeyType, ValueType>, Map.Entry<KeyType, ValueType>, ValueType> another) {
return concat(another.get());
}
protected <Out> TransformRule<Map<KeyType, ValueType>, Map<KeyType, Out>> getMapMapRule(final TransformRule<Map.Entry<KeyType, ValueType>, Out> rule) {
return new TransformRule<Map<KeyType, ValueType>, Map<KeyType, Out>>() {
@Override
public Map<KeyType, Out> extract(Map<KeyType, ValueType> obj) {
Map<KeyType, Out> newOne = new HashMap<>();
for (Map.Entry<KeyType, ValueType> entry : obj.entrySet()) {
newOne.put(entry.getKey(), rule.extract(entry));
}
return newOne;
}
};
}
protected TransformRule<Map<KeyType, ValueType>, Map<KeyType, ValueType>> getMapFilterRule(final FilterRule<Map.Entry<KeyType, ValueType>> rule) {
return new TransformRule<Map<KeyType, ValueType>, Map<KeyType, ValueType>>() {
@Override
public Map<KeyType, ValueType> extract(Map<KeyType, ValueType> obj) {
Map<KeyType, ValueType> newOne = new HashMap<>();
for (Map.Entry<KeyType, ValueType> entry : obj.entrySet()) {
KeyType key = entry.getKey();
ValueType value = entry.getValue();
boolean isValid = rule.apply(entry);
if (isValid) {
newOne.put(key, value);
}
}
return newOne;
}
};
}
}
class FPCollectionContainer<ValueType> extends FPContainer<Collection<ValueType>, ValueType, ValueType> {
FPCollectionContainer(Collection<ValueType> container) {
super(container);
}
@Override
public <Out> FPCollectionContainer<Out> map(TransformRule<ValueType, Out> rule) {
return new FPCollectionContainer<>(handleContainer(getCollectionMapRule(rule)));
}
@Override
public FPCollectionContainer<ValueType> filter(FilterRule<ValueType> rule) {
return new FPCollectionContainer<>(handleContainer(getCollectionFilterRule(rule)));
}
@Override
public FPCollectionContainer<ValueType> concat(Collection<ValueType> another) {
ArrayList<ValueType> newOne = new ArrayList<>(container);
newOne.addAll(another);
return new FPCollectionContainer<>(newOne);
}
@Override
public FPCollectionContainer<ValueType> concat(FPContainer<Collection<ValueType>, ValueType, ValueType> another) {
return concat(another.get());
}
protected <Out> TransformRule<Collection<ValueType>, Collection<Out>> getCollectionMapRule(final TransformRule<ValueType, Out> rule) {
return new TransformRule<Collection<ValueType>, Collection<Out>>() {
@Override
public Collection<Out> extract(Collection<ValueType> obj) {
Collection<Out> newOne = new ArrayList<>();
for (ValueType entry : obj) {
newOne.add(rule.extract(entry));
}
return newOne;
}
};
}
protected TransformRule<Collection<ValueType>, Collection<ValueType>> getCollectionFilterRule(final FilterRule<ValueType> rule) {
return new TransformRule<Collection<ValueType>, Collection<ValueType>>() {
@Override
public Collection<ValueType> extract(Collection<ValueType> obj) {
Collection<ValueType> newOne = new ArrayList<>();
for (ValueType entry : obj) {
if (rule.apply(entry)) {
newOne.add(entry);
}
}
return newOne;
}
};
}
}
abstract class FPContainer<ContainerTypeWithValueType, ContainerIterableItemType, ValueType> {
protected ContainerTypeWithValueType container;
protected FPContainer(ContainerTypeWithValueType container) {
this.container = container;
}
public static <KeyType, ValueType> FPMapContainer<KeyType, ValueType> from(Map<KeyType, ValueType> container) {
return new FPMapContainer<>(container);
}
public static <ValueType> FPCollectionContainer<ValueType> from(Collection<ValueType> container) {
return new FPCollectionContainer<>(container);
}
public abstract <Out> Object map(TransformRule<ContainerIterableItemType, Out> rule);
public abstract FPContainer<ContainerTypeWithValueType, ContainerIterableItemType, ValueType> filter(FilterRule<ContainerIterableItemType> rule);
public abstract FPContainer<ContainerTypeWithValueType, ContainerIterableItemType, ValueType> concat(FPContainer<ContainerTypeWithValueType, ContainerIterableItemType, ValueType> another);
public abstract FPContainer<ContainerTypeWithValueType, ContainerIterableItemType, ValueType> concat(ContainerTypeWithValueType another);
public <Out> Out reduce(TransformRule<ContainerTypeWithValueType, Out> rule) {
return rule.extract(container);
}
public ContainerTypeWithValueType get() {
return container;
}
protected <ContainerTargetType> ContainerTargetType handleContainer(TransformRule<ContainerTypeWithValueType, ContainerTargetType> collectionMapRule) {
if (collectionMapRule != null) {
return collectionMapRule.extract(container);
}
return (ContainerTargetType) container;
}
}
Jetzt können Sie es verwenden, wie Java8Stream auf diese Weise:
TransformRule<Integer, String> integerStringTransform = new TransformRule<Integer, String>() {
@Override
public String extract(Integer obj) {
return "" + obj;
}
};
TransformRule<Collection<String>, String> collectionStringTransform = new TransformRule<Collection<String>, String>() {
@Override
public String extract(Collection<String> obj) {
String result = "";
for (String item : obj) {
result += item;
}
return result;
}
};
FilterRule<Integer> ltFourFilter = new FilterRule<Integer>() {
@Override
public boolean apply(Integer obj) {
return obj != null && obj < 4;
}
};
// ==============================================
String reduced;
// Collection case:
// `reduced` would be "123"
reduced = FPContainer.from(Arrays.asList(1, 4))
.concat(FPContainer.from(Arrays.asList(2)))
.concat(Arrays.asList(3))
.filter(ltFourFilter)
.map(integerStringTransform).reduce(collectionStringTransform);
// Map case:
reduced = FPContainer.from(stringIntegerHashMap)
.filter(new FilterRule<Map.Entry<String, Integer>>() {
@Override
public boolean apply(Map.Entry<String, Integer> obj) {
return obj.getKey().charAt(0) < 'c' && obj.getValue() < 4;
}
})
.map(new TransformRule<Map.Entry<String,Integer>, String>() {
@Override
public String extract(Map.Entry<String, Integer> obj) {
return ""+obj.getValue();
}
}).reduce(new TransformRule<Map<String, String>, String>() {
@Override
public String extract(Map<String, String> obj) {
String result = "";
Map<String, String> objectStringMap = sortByValue(obj);
for (Map.Entry<String, String> entry : objectStringMap.entrySet()) {
result += entry.getKey().toString() + entry.getValue();
}
return result;
}
});
P.S.
sortByValue (Karte) ist hier ein: (Kredit: https://stackoverflow.com/a/109389/2293635)
public static <K, V> Map<K, V> sortByValue(Map<K, V> map) {
List<Map.Entry<K, V>> list = new LinkedList<>(map.entrySet());
Collections.sort(list, new Comparator<Object>() {
@SuppressWarnings("unchecked")
public int compare(Object o1, Object o2) {
return ((Comparable<V>) ((Map.Entry<K, V>) (o1)).getValue()).compareTo(((Map.Entry<K, V>) (o2)).getValue());
}
});
Map<K, V> result = new LinkedHashMap<>();
for (Iterator<Map.Entry<K, V>> it = list.iterator(); it.hasNext();) {
Map.Entry<K, V> entry = (Map.Entry<K, V>) it.next();
result.put(entry.getKey(), entry.getValue());
}
return result;
}
Nein, aber Sie können Scala Stream API Blick in die in der JVM läuft, so dass Sie Ihren Code mischen. Vielleicht ist es nicht genau das, wonach Sie suchen, aber es ist einen Versuch wert, falls nötig. –
Ich denke, das ist eine interessante Frage.Sicherlich benötigen Sie eine Java8 JVM bezüglich der syntaktischen Änderungen in der Sprache für Lambda-Ausdrücke. Streams selbst ist ein Konzept, das vom Compiler nicht implementiert wird; aber nach Klassen in Bibliotheken. Es könnte eine sinnlose Aktivität sein, aber Sie möchten vielleicht einfach die Stream-Quellen von Java8 überprüfen; und prüfen, ob sie in einer Java7-Umgebung kompiliert und ausgeführt werden. – GhostCat
@AlexisC. Das ist ein sehr schöner Vorschlag! Vielen Dank! – Athafoud