Java collection / map apply方法等效吗?

我想将一个函数应用于Java集合,在这种特殊情况下是一个映射。 有一个很好的方法来做到这一点? 我有一个地图,并希望对地图中的所有值运行trim()并让地图反映更新。

使用Java 8的lambda,这是一个单行:

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

为了历史,这里是没有lambdas的版本:

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

或者,更一般地说:

 interface Function { T operate(T val); } public static  void replaceValues(Map map, Function f) { for (Map.Entry e : map.entrySet()) e.setValue(f.operate(e.getValue())); } Util.replaceValues(myMap, new Function() { public String operate(String val) { return (val == null) ? null : val.trim(); } }); 

除了您接受的回复之外,我不知道如何使用JDK库,但Google Collections允许您使用com.google.collect.Mapscom.google.common.base.Function类执行以下操作。 :

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

该方法与提议的方法的最大区别在于它提供了原始地图的视图,这意味着,虽然它始终与原始地图同步,但如果您正在操作所述地图,则可以多次调用apply方法巨资。

Collections2.transform(Collection,Function)类似的Collections2.transform(Collection,Function)方法。

是否可以就地修改集合取决于集合中对象的类。

如果这些对象是不可变的(字符串是),那么你不能只从集合中获取项目并修改它们 – 而是需要迭代集合,调用相关函数,然后将结果值返回。

对于类似这样的事情可能有些过分,但是在Apache Commons Collections库中有很多非常好的实用工具来解决这些类型的问题。

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

我强烈推荐O’Reilly的Jakarta Commons Cookbook 。

我最终使用@ erickson的答案变异,变异为:

  • 返回一个新的Collection ,而不是修改到位
  • 返回Collection ,其类型的元素等于Function的返回类型
  • 支持映射地图的值或列表的元素

码:

 public static interface Function { L operate(R val); } public static  Map map(Map map, Function f) { Map retMap = new HashMap(); for (Map.Entry e : map.entrySet()) retMap.put(e.getKey(), f.operate(e.getValue())); return retMap; } public static  List map(List list, Function f) { List retList = new ArrayList(); for (R e : list) retList.add(f.operate(e)); return retList; } 

您必须迭代所有条目并修剪每个String值。 由于String是不可变的,因此您必须将其重新放入地图中。 更好的方法可能是在将值放在地图中时修剪它们。

我想出了一个“Mapper”课程

 public static abstract class Mapper { private Collection source; // Mapping methods public abstract ToClass map(FromClass source); // Constructors public Mapper(Collection source) { this.source = source; } public Mapper(FromClass ... source) { this.source = Arrays.asList(source); } // Apply map on every item public Collection apply() { ArrayList result = new ArrayList(); for (FromClass item : this.source) { result.add(this.map(item)); } return result; } } 

我这样使用:

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

您还可以查看Google Collections