Frage

Ich möchte eine Funktion auf eine Java-Sammlung anzuwenden, in diesem speziellen Fall eine Karte. Gibt es eine schöne Möglichkeit, dies zu tun? Ich habe eine Karte und möchte nur laufen trim () auf alle Werte in der Karte und haben die Karte, um die Updates zu reflektieren.

War es hilfreich?

Lösung

Mit Java 8 des Lambda, das ist ein Motto:

map.replaceAll((k, v) -> v.trim());

Aus Gründen der Geschichte, hier ist eine Version ohne Lambda-Ausdrücke:

public void trimValues(Map<?, String> map) {
  for (Map.Entry<?, String> e : map.entrySet()) {
    String val = e.getValue();
    if (val != null)
      e.setValue(val.trim());
  }
}

oder allgemeiner:

interface Function<T> {
  T operate(T val);
}

public static <T> void replaceValues(Map<?, T> map, Function<T> f)
{
  for (Map.Entry<?, T> e : map.entrySet())
    e.setValue(f.operate(e.getValue()));
}

Util.replaceValues(myMap, new Function<String>() {
  public String operate(String val)
  {
    return (val == null) ? null : val.trim();
  }
});

Andere Tipps

Ich weiß nicht, einen Weg zu tun, dass mit dem JDK-Bibliotheken anderer als der akzeptierte Antwort, aber Google Kollektionen können Sie das Folgende tun, mit dem Klassen com.google.collect.Maps und com.google.common.base.Function:

Map<?,String> trimmedMap = Maps.transformValues(untrimmedMap, new Function<String, String>() {
  public String apply(String from) {
    if (from != null)
      return from.trim();
    return null;
  }
}

Der größte Unterschied dieses Verfahren mit dem vorgeschlagenen ist, dass es einen Blick auf Ihre Original-Karte bietet, was bedeutet, dass, während es immer synchron mit dem Original-Karte ist, könnte die apply Methode oft aufgerufen werden, wenn Sie Manipulieren der stark kartieren.

Eine ähnliche Collections2.transform(Collection<F>,Function<F,T>) Methode existiert für Sammlungen.

Ob Sie Ihre Sammlung an Ort und Stelle ändern können oder nicht, hängt von der Klasse der Objekte in der Sammlung.

Wenn diese Objekte sind unveränderlich (die Strings sind), dann können Sie nicht nehmen Sie nur die Elemente aus der Sammlung und modifizieren - stattdessen müssen Sie über die Sammlung iterieren, rufen Sie die entsprechende Funktion, und setzen Sie dann die resultierende Wert zurück.

Könnte Overkill für so etwas, aber es gibt eine Reihe von wirklich guten Programmen für diese Art von Problemen in der Jakarta Commons-Kochbuch von O'Reilly .

ich am Ende mit einer Mutation von @ Erickson Antwort, mutiert:

  • Rückkehr eine neue Collection, ändern nicht an Ort und Stelle
  • Rückkehr Collections mit Elementen des Typs gleich den Rückgabetyp der Function
  • Unterstützung Mapping entweder über den Werten einer Karte oder die Elemente einer Liste

Code:

public static interface Function<L, R> {
    L operate(R val);
}

public static <K, L, R> Map<K, L> map(Map<K, R> map, Function<L, R> f) {
    Map<K, L> retMap = new HashMap<K, L>();

    for (Map.Entry<K, R> e : map.entrySet()) retMap.put(e.getKey(), f.operate(e.getValue()));

    return retMap;
}

public static <L, R> List<L> map(List<R> list, Function<L, R> f) {
    List<L> retList = new ArrayList<L>();

    for (R e : list) retList.add(f.operate(e));

    return retList;
}

Sie werden über alle Einträge durchlaufen müssen und jeden String-Wert trimmen. Da String unveränderlich ist haben Sie es in der Karte neu zu setzen. Ein besserer Ansatz könnte sein, die Werte zu trimmen, wie sie in der Karte platziert sind.

Ich habe mit einer "Mapper" Klasse kommen

public static abstract class Mapper<FromClass, ToClass> {

    private Collection<FromClass> source;

    // Mapping methods
    public abstract ToClass map(FromClass source);

    // Constructors
    public Mapper(Collection<FromClass> source) {
        this.source = source;
    }   
    public Mapper(FromClass ... source) {
        this.source = Arrays.asList(source);
    }   

    // Apply map on every item
    public Collection<ToClass> apply() {
        ArrayList<ToClass> result = new ArrayList<ToClass>();
        for (FromClass item : this.source) {
            result.add(this.map(item));
        }
        return result;
    }
}

Dass ich so verwenden:

Collection<Loader> loaders = new Mapper<File, Loader>(files) {
    @Override public Loader map(File source) {
        return new Loader(source);
    }           
}.apply();

Sie können auch einen Blick auf Google Kollektionen nehmen

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top