Issue
I am creating an ArrayList of an array and then returning the data in the form of a Stream from the method. But I need a stream of the objects inside the array. I believe I need to use href="https://stackoverflow.com/questions/51476199/flatmap-a-stream-of-a-collection-to-a-stream-of-its-elements">flatMap() but what I have is not working for me, whereas when I return Stream.of(Arguments.of(kt,r,expectedPoints));
It works, and I see the Objects correctly in my unit test.
class KdTreeTest {
static class KdTreeArgumentsProvider implements ArgumentsProvider {
final static File folder = new File("src/main/resources/kdtests/");
KdTree kt = new KdTree();
RectHV r = new RectHV(0.1, 0.1, 0.5, 0.6);
Point2D p1 = new Point2D(0.1, 0.2);
Point2D p2 = new Point2D(0.8, 0.9);
Point2D[] expectedPoints = {p1, p2};
@Override
public Stream<? extends Arguments> provideArguments(ExtensionContext extensionContext) throws Exception {
Object[] instanceData = new Object[3];
List<Object> l = new ArrayList<>();
for (final File fileEntry : folder.listFiles()) {
String fileName = fileEntry.getName().toUpperCase();
if (fileName.endsWith(".TXT")) {
Scanner scanner = new Scanner(fileEntry);
kt = new KdTree();
while (scanner.hasNext()) {
double x = scanner.nextDouble();
double y = scanner.nextDouble();
Point2D p = new Point2D(x, y);
kt.insert(p);
}
instanceData[0] = kt;
instanceData[1] = r;
instanceData[2] = expectedPoints;
l.add(instanceData);
}
}
return Stream.of(Arguments.of((l.stream().flatMap(x->Stream.of("x[0]","x[1]","x[2]")))));
}
}
@DisplayName("should create a rectangle with the given coordinates and test KdTree's range() function")
@ParameterizedTest(name = "{index}=> kt={0},r={1},expectedPoints={2}")
@ArgumentsSource(KdTreeArgumentsProvider.class)
void range(KdTree kt, RectHV r, Point2D[] expectedPoints) {
Assertions.assertNotNull(kt.range(r));
}
}
I think I can just put everything in an Object[] from the beginning, but just our of curiosity is there a way to do this with Stream methods?
Solution
If I'm understanding correctly what you're trying to do, then you need to make two changes:
Change the type of
l
fromList<Object>
toList<Object[]>
:List<Object[]> l = new ArrayList<>();
Change the return statement to:
return l.stream() .map(Arguments::of);
Unpacking this:
l.stream
produces aStream<Object[]>
froml
map(Arguments::of)
callsArguments.of
on each array in the stream, creating anArguments
object with three entries, matching the arguments of therange
method
You don't want to flatten the array into the stream, because that would result in a stream of Arguments
objects with a single element.
Answered By - Tim Moore
Answer Checked By - Clifford M. (JavaFixing Volunteer)