java streams in Java 7

后端 未结 3 1278
[愿得一人]
[愿得一人] 2020-12-03 09:55

My question may be too broad and probably the answer is a simple NO, but I have to ask.

Is there any equivalent implementation of (Java 8) streams* in Java 7?

<
相关标签:
3条回答
  • 2020-12-03 10:47

    In the official API, no.

    There is no more public updates for Java 7. If you're a customer, you might still get minor updates, but this not (or very very very unlikely) for back-porting the Stream API.

    With a bit of digging you may look at StreamSupport. I've never tested it but apparently its goal is to backport the Stream API to Java 6/7 and if you want to combine it with lambda expressions there's also retrolambda.

    Functional Java can be interesting. It's not exactly the same intent as the Stream API but if your goal is to filter/map/etc. a list/array it might suits your needs. For example:

    final List<Integer> b = list(1, 2, 3).map(add.f(-1));
    listShow(intShow).println(b); // [0, 1, 2]
    

    Finally you can look into the Scala's Stream API. As Scala runs also on the JVM, you can mix your code. Maybe it's not exactly what you are looking for but it's worth a try if needed.

    0 讨论(0)
  • 2020-12-03 10:51

    An another choice is here for Java 6+

    interfaces:

    interface TransformRule<In, Out> {
        Out extract(In obj);
    }
    
    interface FilterRule<T> {
        boolean apply(T obj);
    }
    

    And Java8Stream-like container class for Collection/Map:

    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;
        }
    }
    

    Now you can use it like Java8Stream in this way:

    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(map) is here: (credit: 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;
    }
    
    0 讨论(0)
  • 2020-12-03 10:53

    Google's Guava library contains some functional idioms for Java versions 5 to 7:

    https://github.com/google/guava/wiki/FunctionalExplained

    Also, there is this library that you may want to check (I haven't heard of it up until some minutes ago when I performed a Google search :-) )

    http://www.functionaljava.org/

    0 讨论(0)
提交回复
热议问题