如何在Java 8中返回一个删除了一个条目的Map

时间:2017-08-10 07:53:40

标签: java functional-programming hashmap

使用Java 8我有一个Map<String, String>我希望使用其中一个标准库的方法来返回一个Map并删除指定的条目。

所以基本上我正在寻找一种通过函数调用或函数连接来实现的方法以下(假设的)Map方法:

Map<String, String> removed(String key) {
    this.remove(key);
    return this;
}

整件事情可以帮助我将Map Bean转换为一行中的漂亮字符串

2 个答案:

答案 0 :(得分:1)

不修改输入映射的版本可能如下所示。

return map.entrySet().stream()
  .filter(e -> !e.getKey().equals(other))
  .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

是的,我认为它不会比这更容易。

答案 1 :(得分:1)

如果你想要做的就是实现一个toString()方法来跳过"class"属性,你可以直接这样做而无需操纵Map

@Override
public String toString() {
    return BeanUtils.describe(this).entrySet().stream()
        .filter(e -> !e.getKey().equals("class"))
        .map(Object::toString)
        .collect(Collectors.joining("\n", super.toString()+":\n", ""));
}

但是对我来说,首先不能排除class财产,看起来像是一个不幸的遗漏。考虑:

public class MyBeanUtils {
    public static Map<String,Object> describe(Object o) {
        try {
            return describe(o, Introspector.getBeanInfo(o.getClass()));
        } catch (IntrospectionException ex) {
            throw new IllegalStateException(ex);
        }
    }
    public static Map<String,Object> describe(Object o, Class<?> stopClass) {
        try {
            return describe(o, Introspector.getBeanInfo(o.getClass(), stopClass));
        } catch (IntrospectionException ex) {
            throw new IllegalStateException(ex);
        }
    }
    private static Map<String,Object> describe(Object o, BeanInfo beanInfo) {
        Map<String,Object> map=new HashMap<>();
        for(PropertyDescriptor fd: beanInfo.getPropertyDescriptors()) {
            if(fd.getReadMethod()!=null) try {
                map.put(fd.getName(), fd.getReadMethod().invoke(o));
            } catch(IllegalAccessException | InvocationTargetException ex){}
        }
        return map;
    }
}

现在,通过将Object.class指定为停止类,我们会排除其属性,这正是class定义的Object.getClass()属性:

@Override
public String toString() {
    return MyBeanUtils.describe(this, Object.class).entrySet().stream()
        .map(Object::toString)
        .collect(Collectors.joining("\n", super.toString()+":\n", ""));
}

这甚至可以提供另一个机会。如果我们假设super.toString()已经关注超类层次结构的所有属性,我们可以将自己的超类指定为停止类,只添加在我们类中定义的属性:

public class BeanExample extends JButton {
    String foo = "some string";
    int bar = 42;

    public String getFoo() {
        return foo;
    }
    public void setFoo(String foo) {
        this.foo = foo;
    }
    public int getBar() {
        return bar;
    }
    public void setBar(int bar) {
        this.bar = bar;
    }
    @Override
    public String toString() {
        return MyBeanUtils.describe(this, getClass().getSuperclass()).entrySet().stream()
            .map(Object::toString)
            .collect(Collectors.joining("\n", super.toString()+":\n", ""));
    }
}

BeanExample[,0,0,0x0,invalid,alignmentX=0.0,alignmentY=0.5,border=javax.swing.plaf.BorderUIResource$CompoundBorderUIResource@b1bc7ed,flags=296,maximumSize=,minimumSize=,preferredSize=,defaultIcon=,disabledIcon=,disabledSelectedIcon=,margin=javax.swing.plaf.InsetsUIResource[top=2,left=14,bottom=2,right=14],paintBorder=true,paintFocus=true,pressedIcon=,rolloverEnabled=true,rolloverIcon=,rolloverSelectedIcon=,selectedIcon=,text=,defaultCapable=true]:
bar=42
foo=some string