I have a class like this
public class Host {
private HTMLToken.TokenType type;
private StringBuilder content;
public Host(HTMLToken.TokenType type) {
this.type = type;
content = new StringBuilder();
}
String contentAsString() {
return content.toString();
}
void addStrig(String x) {
content.append(x);
}
public enum TokenType {
TAG, TEXT
}
}
and static function like this
public static String[] filterLength(List<Host> hostList, int length) {
return hostList.stream().filter(str -> str.contentAsString().length() > length)
.toArray(String[]::new);
}
The problem is inside of filterLength function I can’t return stream as a String array(I want to return content in the Host class) because List holds Host object how can I return as a string in 1 line code?
Advertisement
Answer
Transform each object in stream
You are successfully streaming, filtering, and collecting a bunch of Host objects into an array. But you seem to be asking how to instead collect a string representation of each Host object.
So, you need to add a step to your streaming operations. For each Host object, we want to generate and collect a String object.
Stream#map
To transform from the objects being streamed to a different kind of object, use Stream#map.
Here is an analog of your code, using LocalDate. We transform each filtered LocalDate object to a String object by passing a method reference: LocalDate :: toString.
List < LocalDate > dates = new ArrayList<>( 4 ) ;
dates.add( LocalDate.of( 2022 , Month.JANUARY, 11 ) ) ;
dates.add( LocalDate.of( 2022 , Month.JANUARY, 12 ) ) ;
dates.add( LocalDate.of( 2022 , Month.JANUARY, 13 ) ) ;
dates.add( LocalDate.of( 2022 , Month.JANUARY, 14 ) ) ;
String[] results =
dates
.stream()
.filter( localDate -> localDate.getDayOfMonth() > 12 )
.map( LocalDate :: toString ) // ð
.toArray( String[] :: new ) ;
System.out.println( "results = " + String.join( ", " , results ) ) ;
See this code run live at IdeOne.com.
results = 2022-01-13, 2022-01-14
I see you have a contentAsString method. I will guess that method returns the kind of text you want to collect.
So your code should be something like the following, passing method reference Host :: contentAsString to Stream#map.
return
hostList
.stream()
.filter( str -> str.contentAsString().length() > length )
.map( host -> Host::contentAsString ) // ð Add this step.
.toArray( String[]::new );
That code is effective but inefficient. No need to execute contentAsString method twice per input. We can fix this by putting the map call first, then filter based on the length of the already-produced string.
return
hostList
.stream()
.map( host -> Host::contentAsString ) // ð Add this step.
.filter( string -> string.length() > length ) // ð Change this step.
.toArray( String[]::new );