我想将一个函数应用于 Java 集合,在本例中是一个映射。有什么好的方法可以做到这一点吗?我有一张地图,只想对地图中的所有值运行 trim() 并让地图反映更新。

有帮助吗?

解决方案

使用的Java 8的lambda表达式,这是一个一个衬里:

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

有关历史的缘故,这里的lambda表达式没有一个版本:

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

或者,更一般地:

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

其他提示

我不知道的方式做到这一点与JDK库比你接受响应等,但谷歌集合让你做以下的事情,用类com.google.collect.Mapscom.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;
  }
}

所提出的一个方法的最大区别在于,它提供了一个以你原来的地图,这意味着,虽然它总是与你的原始地图同步,该apply方法可以调用很多次,如果你是操纵所说的映射严重。

一个类似Collections2.transform(Collection<F>,Function<F,T>)方法存在的集合。

您是否可以修改您的收藏就地或不依赖于集合类中的对象。

如果这些对象是不可变的(这是字符串),那么你不能只是采取从集合中的项目并修改它们 - 而不是你需要遍历集合,调用相关功能,然后把得到的值返回。

可能是矫枉过正这样的事情,但也有一些真正的好工具,用于这些类型的问题中的 Apache的百科全书类别库。

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"));

我强烈推荐 Jakarta通用食谱由O'Reilly 的。

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

  • 返回一个新的 Collection, ,不就地修改
  • 返回 Collections 的元素类型等于 the 返回类型 Function
  • 支持映射映射的值或列表的元素

代码:

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

您必须遍历所有条目,并调整每个字符串值。由于字符串是不可变的,你将不得不重新把它在地图上。一种更好的方法可能是修剪的值,因为它们可以放置在地图上。

我已经提出了一个“映射器”类

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

,我使用这样的:

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

您也可以看看谷歌集合

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top