2015-05-05 16 views
22

La mia domanda potrebbe essere troppo ampia e probabilmente la risposta è un semplice NO, ma devo chiedere.java streams in Java 7

Esiste un'implementazione equivalente di (Java 8) streams * in Java 7?

mi è familiare (Java 8) i flussi, ma la mia esigenza progettuale è quello di utilizzare Java 7.

* Da non confondere con inputStream e outputStream.

+5

No. Ma si può guardare in API flusso di Scala che scorre nella JVM in modo da poter mescolare il vostro codice. Forse non è esattamente quello che stai cercando, ma vale la pena provare se necessario. –

+0

Penso che questa sia una domanda interessante.Di sicuro, è necessaria una JVM Java8 per quanto riguarda le modifiche sintattiche alla lingua per le espressioni lambda. Ma lo stesso stream è un concetto che non è implementato dal compilatore; ma per classi nelle biblioteche. Potrebbe essere un'attività inutile, ma potreste voler semplicemente controllare i sorgenti degli stream da Java8; e vedere se compilano ed eseguono in un ambiente Java7. – GhostCat

+0

@AlexisC. È un suggerimento molto carino! Grazie! – Athafoud

risposta

18

Nel API ufficiali, no.

Non ci sono altri aggiornamenti pubblici per Java 7. Se sei un cliente, potresti comunque ricevere aggiornamenti minori, ma questo non è (o molto molto improbabile) per il back-porting dell'API Stream.

Con un po 'di scavo si può guardare StreamSupport. Non l'ho mai testato ma a quanto pare il suo obiettivo è quello di eseguire il backport dell'API Stream su Java 6/7 e, se si desidera combinarlo con espressioni lambda, c'è anche retrolambda.

Functional Java può essere interessante. Non è esattamente la stessa intenzione dell'API Stream, ma se il tuo obiettivo è filtrare/mappare/etc. una lista/matrice potrebbe essere adatta alle tue esigenze. Per example:

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

Infine si può guardare in API flusso della Scala. Poiché Scala funziona anche su JVM, puoi combinare il tuo codice. Forse non è esattamente quello che stai cercando, ma vale la pena provare se necessario.

+0

Java 7 può ancora essere utilizzato per gli ambienti di produzione: la "fine vita" è solo per gli aggiornamenti gratuiti. Se un cliente acquista supporto da Oracle, riceverà comunque aggiornamenti e correzioni di errori (anche per versioni precedenti come Java 6 o Java 5). Quindi in questo caso è perfettamente corretto sviluppare software con Java runtime di destinazione. – mschenk74

+2

L'idea di mixare java con il codice scalla è molto interessante. streamsupport è anche un buon modo per andare. – Athafoud

+2

@ mschenk74 Non ho detto che non dovrebbe essere usato per gli ambienti di produzione. Potresti ricevere aggiornamenti minori, ma volevo sottolineare che è improbabile che questi aggiornamenti eseguano il backport dell'API Stream in Java 7, IMO. –

8

biblioteca Guava di Google contiene alcuni idiomi funzionali per le versioni di Java 5 a 7:

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

Inoltre, c'è questa libreria che si consiglia di controllare (non ho sentito parlare fino fino a qualche minuto fa, quando ho eseguito una ricerca di Google :-))

http://www.functionaljava.org/

+0

Penso che "funzionale" sia la parola magica per la ricerca su google, non l'ho pensato prima. Non ero a conoscenza di quella funzionalità di Guava, ma la documentazione sembra buona. functionaljava.org sembra un po '"disordinato" ma ci provo! – Athafoud

2

Un un'altra scelta è qui per Java 6+

interfacce:

interface TransformRule<In, Out> { 
    Out extract(In obj); 
} 

interface FilterRule<T> { 
    boolean apply(T obj); 
} 

E Java8Stream-come classe contenitore per la raccolta/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; 
    } 
} 

Ora è possibile utilizzarlo come Java8Stream in questo modo:

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 (mappa) è qui: (credito: 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; 
}