Java collection/map apply method equivalent?

后端 未结 8 482
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-13 19:27

I would like to apply a function to a Java collection, in this particular case a map. Is there a nice way to do this? I have a map and would like to just run trim() on all t

相关标签:
8条回答
  • 2020-12-13 20:02

    Might be overkill for something like this, but there are a number of really good utilities for these types of problems in the Apache Commons Collections library.

    Map<String, String> map = new HashMap<String, String>(); 
    map.put("key1", "a  ");
    map.put("key2", " b ");
    map.put("key3", "  c");
    
    TransformedMap.decorateTransform(map, 
      TransformerUtils.nopTransformer(), 
      TransformerUtils.invokerTransformer("trim"));
    

    I highly recommend the Jakarta Commons Cookbook from O'Reilly.

    0 讨论(0)
  • 2020-12-13 20:05

    You could also take a look at Google Collections

    0 讨论(0)
  • 2020-12-13 20:09

    I don't know a way to do that with the JDK libraries other than your accepted response, however Google Collections lets you do the following thing, with the classes com.google.collect.Maps and 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;
      }
    }
    

    The biggest difference of that method with the proposed one is that it provides a view to your original map, which means that, while it is always in sync with your original map, the apply method could be invoked many times if you are manipulating said map heavily.

    A similar Collections2.transform(Collection<F>,Function<F,T>) method exists for collections.

    0 讨论(0)
  • 2020-12-13 20:14

    You'll have to iterate over all the entries and trim each String value. Since String is immutable you'll have to re-put it in the map. A better approach might be to trim the values as they're placed in the map.

    0 讨论(0)
  • 2020-12-13 20:15

    With Java 8's lambdas, this is a one liner:

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

    For the sake of history, here's a version without lambdas:

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

    Or, more generally:

    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();
      }
    });
    
    0 讨论(0)
  • 2020-12-13 20:19

    I ended up using a mutation of @erickson's answer, mutated to:

    • return a new Collection, not modify in place
    • return Collections with elements of type equal to the return type of the Function
    • support mapping over either the values of a map or the elements of a list

    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;
    }
    
    0 讨论(0)
提交回复
热议问题