variante funcional del valor get desde if-elseif-else, en Java

Eric Lilja:

Tuve que procesar algunos JSON, lo que podría venir en formatos ligeramente diferentes (y donde sólo necesitaba un subconjunto de los datos JSON) y solía JsonPointer (de Jackson) para consultar el JSON. Escribí una solución no funcional al problema, que trabajó para mí, pero quería probar un enfoque funcional con fines de aprendizaje. En el programa de pruebas a continuación se puede ver mis dos soluciones. Ambos trabajan, pero la solución funcional volvió bastante detallado y tengo una advertencia molesto de IntelliJ relacionadas con la utilización get () sin verificación de isPresent. Me gustaría ver cómo las propuestas para mejorar la aplicación funcional y estoy feliz de ver soluciones que utilizan las bibliotecas de terceros. El problema básico aquí, supongo, es cómo modelar un if-else-if-else, donde cada rama debe devolver algún valor, de una manera funcional.

@Test
public void testIt() {
    ObjectMapper om = new ObjectMapper();
    ImmutableList.of(
            "{ \"foo\": { \"key\": \"1\" } }",
            "{ \"bar\": { \"key\": \"1\" } }",
            "{ \"key\": \"1\" }")
            .forEach(str -> {
                try {
                    System.out.println("Non-functional: " + getNode(om.readTree(str)));
                    System.out.println("Functional: " + getNodeFunc(om.readTree(str)));
                } catch (Exception e) {
                    throw new RuntimeException("", e);
                }
            });
}

private JsonNode getNode(JsonNode parentNode) {
    JsonPointer jp1 = JsonPointer.compile("/foo");
    JsonPointer jp2 = JsonPointer.compile("/bar");
    if (!parentNode.at(jp1).isMissingNode()) {
        return parentNode.at(jp1);
    } else if (!parentNode.at(jp2).isMissingNode()) {
        return parentNode.at(jp2);
    }
    return parentNode;
}

private JsonNode getNodeFunc(JsonNode parentNode) {
    BiFunction<JsonNode, String, Optional<JsonNode>> findNode = (node, path) -> {
        JsonPointer jp = JsonPointer.compile(path);
        return node.at(jp).isMissingNode() ? Optional.empty() : Optional.of(node.at(jp));
    };

    return findNode.apply(parentNode, "/foo")
            .map(Optional::of)
            .orElseGet(() -> findNode.apply(parentNode, "/bar"))
            .map(Optional::of)
            .orElse(Optional.of(parentNode))
            .get(); // Intellij complains here: Optional.get() without isPresent check
}
Andrew Tobilko:

Me gustaría volver a escribir a

private JsonNode getNodeFunc2(JsonNode parentNode) {
    return Stream.of(JsonPointer.compile("/foo"), JsonPointer.compile("/bar"))
                 .filter(i -> !parentNode.at(i).isMissingNode())
                 .findFirst()
                 .map(parentNode::at)
                 .orElse(parentNode);
}

o

private JsonNode getNodeFunc3(JsonNode parentNode) {
    return Stream.of(JsonPointer.compile("/foo"), JsonPointer.compile("/bar"))
                 .map(parentNode::at)
                 .filter(Predicate.not(JsonNode::isMissingNode))
                 .findFirst()
                 .orElse(parentNode);
}

o

private JsonNode getNodeFunc4(JsonNode parentNode) {
    return Stream.of("/foo", "/bar")
                 .map(JsonPointer::compile)
                 .map(parentNode::at)
                 .filter(Predicate.not(JsonNode::isMissingNode))
                 .findFirst()
                 .orElse(parentNode);
}

porque la pieza

if (!parentNode.at(jp1).isMissingNode()) {
    return parentNode.at(jp1);
} else if (!parentNode.at(jp2).isMissingNode()) {
    return parentNode.at(jp2);
}

es la duplicación de código y puede ser manejado cuidadosamente por un bucle:

for (JsonPointer jsonPointer : jsonPointers) {
    JsonNode kid = parentNode.at(jsonPointer);
    if (!kid.isMissingNode()) {
         return kid;
    }
}

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=207028&siteId=1
Recomendado
Clasificación