我想用功能样式重写以下逻辑, ie 使用map
,filter
,ifPresent
,{{1} },orElse
,orElseGet
等
orElseThrow
我遇到的主要问题是String id;
if (entity.legacyIndicator().isPresent()) { // field is an Optional<Foo>
if (entity.legacyId().isPresent()) { // field is an Optional<Long>
id = entity.legacyId().toString(); // e.g. id = '01234567'
} else {
throw new IOException("No ID found.");
}
} else {
if (entity.newId().isPresent()) { // field is an Optional<UUID>
id = entity.newId().toString(); // e.g. id = '01234567-89ab-cdef-0123-456789abcdef'
} else {
throw new IOException("No ID found.");
}
}
和legacyId()
是不同的类型。我如何统一&#34;两个分支都认为我作为程序员知道他们共享newId()
和isPresent()
,但不共享实际界面?
我将尽快编辑这个问题,因为我还在尽力而为。但我总是难以统一分支机构。
答案 0 :(得分:2)
好的,不是很干净,但我会选择像
这样的东西 public String getId(Test.Entity entity) throws Throwable {
return entity.legacyIndicator()
.map(o -> (Optional) entity.legacyId())
.orElseGet(() -> (Optional) entity.newId())
.orElseThrow(() -> new IOException("No ID found."))
.toString();
}
这里有一些Junit测试来验证执行
@org.junit.Test
public void test() throws Throwable {
Entity entity = new Entity();
entity.legacyIndicator = Optional.empty();
final UUID uuid = UUID.randomUUID();
entity.newId = Optional.of(uuid);
String id = getId(entity);
Assert.assertEquals(uuid.toString(), id);
entity = new Entity();
entity.legacyIndicator = Optional.of(Boolean.TRUE);
entity.newId = Optional.of(uuid);
entity.legacyId = Optional.of("SomeId");
id = getId(entity);
Assert.assertEquals("SomeId", id);
}
@org.junit.Test(expected = IOException.class)
public void testExceptionLegacy() throws Throwable {
Entity entity = new Entity();
entity.legacyIndicator = Optional.of(Boolean.TRUE);
entity.legacyId = Optional.empty();
String id = getId(entity);
}
@org.junit.Test(expected = IOException.class)
public void testExceptionNew() throws Throwable {
Entity entity = new Entity();
entity.legacyIndicator = Optional.empty();
entity.legacyId = Optional.empty();
entity.newId = Optional.empty();
String id = getId(entity);
}
class Entity {
Optional<Boolean> legacyIndicator;
Optional<String> legacyId;
Optional<UUID> newId;
Optional<Boolean> legacyIndicator() {
return legacyIndicator;
}
Optional<UUID> newId() {
return newId;
}
Optional<String> legacyId() {
return legacyId;
}
}
答案 1 :(得分:1)
是的,你可以做到,但是我们没有&#34; 1-liner&#34;作为避免混淆的要求。类似于Optional<String>
和Optional<UUID>
的类型是Optional<?>
:
boolean legacy = entity.legacyIndicator().isPresent(); // weird use of Optional
// shouldn't it be a boolean?
Optional<?> optId = legacy ? entity.legacyId() : entity.newId();
String id = optId.orElseThrow(() -> new IOException("ID not found")).toString();
或者,您可以在toString
链中进行Optional
,如果您发现更清楚的话:
String id = optId.map(Object::toString).orElseThrow(...);
现在,如果您想要的话,可以将它们全部组合成1个班轮:
String id = (entity.legacyIndicator().isPresent() ? entity.legacyId() : entity.newId())
.orElseThrow(() -> new IOException("ID not found"))
.toString();
答案 2 :(得分:0)
因为我不能像@Vyncent建议的那样强制转换为Optional<Object>
,所以我最终不得不将分支分开:
String id = entity.legacyIndicator().isPresent()
? entity.legacyId().orElseThrow(() -> new IOException("No ID found.")).toString()
: entity.newId().orElseThrow(() -> new IOException("No ID found.")).toString();
从我所做的研究中,如果没有实际创建通用,就不可能拥有“通配符”类型。尽管如此开放!