user148095 user148095 - 6 months ago 14
Java Question

Java 8 stream api control output

I have the following code.

List<String> parseAttribValueByTag(String tag, String attrib, List<String> attribName) throws IOException {

List<String> keys = new ArrayList<>();

Document doc = Jsoup.connect(url).get();
Elements inputs = doc.select(tag + "[" + attrib + "]");
for (String item : attribName) {
System.out.println(inputs.stream()
.filter(input -> input.attr("name").contains("__VIEWSTATE"))
.findFirst());
}
return keys;
}


It gives me the following output

Optional[<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="5ue/NxnSLQ2akzQo5R8wBEZ,,."


I would like to control the output so it only gives me
__VIEWSTATE "5ue/NxnSLQ2akzQo5R8wBEZ,,."


I've tried using
.map(input -> input.attr("value"))
and it gives me
Optional[5ue/NxnSLQ2akzQo5R8wBEZ,,.


but when I add an additional
.map(input -> input.attr("name"))
to also give me the name I get the following error "Cannot resolve method 'attr(java.lang.String)' ". What is it I'm doing wrong in the code? Is there a way around it?

Answer

If you add a .map(input -> input.attr("value")), you convert your Stream to a Stream<String> (assuming that attr returns a String), and String doesn't have an attr method, so the second map call doesn't pass compilation (hence the compilation error - Cannot resolve method 'attr(java.lang.String)').

You could use a single map operation to obtain both attributes. For example :

    System.out.println(inputs.stream()
        .filter(input -> input.attr("name").contains("__VIEWSTATE"))
        .map(input -> input.attr("name") + " " + input.attr("value"))
        .findFirst());