Java 8可选,多个过滤器和多个映射

时间:2016-01-28 15:19:57

标签: java java-8

我想使用Java 8,如何在java 8 Optional中将这种命令式样式设置为功能样式?

例如,假设 exchange.getIn()。getBody()可能为null。

public class Section1 : ConfigurationSection
{
    public const string SectionName = "Section1";

    private const string FieldDefinitionsCollectionName = "Section1FieldDefinitions";

    [ConfigurationProperty(FieldDefinitionsCollectionName)]
    [ConfigurationCollection(typeof(Section1Collection),
        AddItemName = "add",
        ClearItemsName = "clear",
        RemoveItemName = "remove")]
    public Section1 Items
    {
        get
        {
            return (Section1Collection)base[FieldDefinitionsCollectionName];
        }
    }
}

public class Section1Collection : ConfigurationElementCollection 
{
    public Section1Collection()
    {
    }

    public Section1FieldDefinitionsElement this[int index]
    {
        get
        {
            return (Section1FieldDefinitionsElement)BaseGet(index);
        }
        set
        {
            if (BaseGet(index) != null)
            {
                BaseRemoveAt(index);
            }
            BaseAdd(index, value);
       }    
    }

    public void Add(SectionFieldDefinitionsElement pSection1)
    {
        BaseAdd(pSection1);
    }

    public void Clear()
    {
        BaseClear();
    }

    protected override ConfigurationElement CreateNewElement()
    {
        return new Section1FieldDefinitionsElement();
    }

    protected override object GetElementKey(ConfigurationElement element)
    {
        return ((Section1FieldDefinitionsElement)element).ID;
    }

    public void Remove(Section1FieldDefinitionsElement pSection1)
    {
        BaseRemove(pSection1.ID);
    }

    public void Remove(string name)
    {
        BaseRemove(name);
    }

    public void RemoveAt(int index)
    {
        BaseRemoveAt(index);
    }
}

public class Section1FieldDefinitionsElement : ConfigurationElement
{
    [ConfigurationProperty("id", IsRequired = true)]
    public string ID
    {
        get
        {
            return (string)this["id"];
        }
        set
        {
            this["id"] = value;
        }
    }

    [ConfigurationProperty("project", IsRequired = true)]
    public string Project
    {
        get 
        {
            return (string)this["project"]; 
        }
        set 
        { 
            this["project"] = value; 
        }
    }

    [ConfigurationProperty("browsername", IsRequired = true)]
    public string Browsername
    {
        get
        {
            return (string)this["browsername"];
        }
        set
        {
            this["browsername"] = value;
        }
    }
}

也许这样的事情,但我需要它在一个班轮。

String color = null;
if(exchange.getIn().getBody() instanceof Foo) {
    color = "toFoo";
} else if(exchange.getIn().getBody() instanceof Bar){
    color = "toBar";
}

我的问题是地图已经是一个字符串,所以我无法将其作为一个字符串:

 Optional.ofNullable(exchange.getIn().getBody())
         .filter(body -> body instanceof Foo)
         .map(body ->  "toFoo");

2 个答案:

答案 0 :(得分:3)

你想要做的是模式匹配,这不是Optional的用途。您可以滥用Optional来获得产生所需结果的内容,例如

Object o=exchange.getIn().getBody();
String color=Optional.ofNullable(o).filter(Foo.class::isInstance).map(x->"toFoo")
    .orElseGet(()->Optional.ofNullable(o).filter(Bar.class::isInstance).map(x->"toBar")
    .orElse("fallback"));

但这显然不是真正的胜利,特别是如果你考虑将会发生什么,当你添加更多的案例时。

实现目标的一种方法是通过Map

关联谓词和结果
Map<Predicate<Object>,String> alternatives=new HashMap<>();
alternatives.put(Bar.class::isInstance, "toBar");
alternatives.put(Foo.class::isInstance, "toFoo");

Object o=exchange.getIn().getBody();
String color=alternatives.entrySet().stream()
    .filter(e->e.getKey().test(o))
    .findAny().map(Map.Entry::getValue).orElse("fallback");

这执行线性搜索(没有特定顺序,因此谓词必须是析取的),这适用于少数情况,并且您可以添加另一个简单的案例

alternatives.put(Baz.class::isInstance, "toBaz");

但是对于大量的情况,以允许有效查找的方式编码谓词(例如,使用类作为映射键并动态添加遇到的子类)是可取的。

请注意,上面的两个示例使用"fallback"作为未满足谓词的情况的值。您只需将其替换为null即可获得与问题代码相同的后备结果。

答案 1 :(得分:1)

为了得到你的单行,我会转过来#34;类似的逻辑:

Object body = exchange.getIn().getBody();
Stream.of(
  new Pair<Class, String>(Foo.class, "toFoo"), 
  new Pair<Class, String>(Bar.class, "toBar"))
      .filter(pair -> body != null && body.getClass().isAssignableFrom(pair.getKey())))
      .findFirst()
      .map(Pair::getValue)
      .orElse("default");