Java 集合/映射应用方法等效吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/744435/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 18:58:05  来源:igfitidea点击:

Java collection/map apply method equivalent?

javacollectionsapply

提问by joshjdevl

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 the values in the map and have the map reflect the updates.

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

采纳答案by erickson

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

使用 Java 8 的 lambdas,这是一个单行代码:

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

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

为了历史起见,这里有一个没有 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();
  }
});

回答by Alnitak

Whether you can modify your collection in-place or not depends on the class of the objects in the collection.

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

If those objects are immutable (which Strings are) then you can't just take the items from the collection and modify them - instead you'll need to iterate over the collection, call the relevant function, and then put the resulting value back.

如果这些对象是不可变的(字符串是),那么您不能只从集合中获取项目并修改它们 - 相反,您需要遍历集合,调用相关函数,然后将结果值放回去。

回答by Steve Kuo

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.

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

回答by CoverosGene

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 Collectionslibrary.

对于这样的事情可能有点矫枉过正,但是Apache Commons Collections库中有许多非常好的实用程序可以解决这些类型的问题。

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 Cookbookfrom O'Reilly.

我强烈推荐O'Reilly的Jakarta Commons Cookbook

回答by Fortyrunner

You could also take a look at Google Collections

你也可以看看谷歌收藏

回答by Jean Hominal

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.Mapsand com.google.common.base.Function:

除了您接受的响应之外,我不知道使用 JDK 库的方法,但是 Google Collections 允许您使用类com.google.collect.Maps和执行以下操作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 applymethod could be invoked many times if you are manipulating said map heavily.

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

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

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

回答by Raphael Jolivet

I have come up with a "Mapper" class

我想出了一个“映射器”类

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

That I use like that :

我这样使用:

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

回答by nmr

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

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

  • 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
  • 返回一个新的Collection,而不是就地修改
  • 返回Collection元素类型等于返回类型的 sFunction
  • 支持映射映射的值或列表的元素

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