Computer Science Courses
Related sites
HW 6 |
To practice the use of stream pipelines for creatinga complex data structures, and define a necessary "building infrastructure"when not relying on the standard API container. The material needed for thishomework has been discussed in and lectures. Also, consultthe textbook, Java Tutorial or any other suitable sources.
This homework is to be done in conjunction with , preferably after completing that Lab.
(not quite Java programming)
Donald "You're Fired!" Trump is a frontrunner for the republican nomination as a candidate for 2016 presidential elections in the US-of-A. One of his election promises was to build a wall along the US–Mexico border to prevent illegal immigration. We shall build this wall for him.
The original code consists of four source files:
balls
) from which the stream is made of originally; instances of Ball are created with a randomly chosen colourballs
are converted (mapped) during the stream operations; bricks
are created from balls
to the same "mass" (naturally)brick
s are reduce
d to a wall
, or collect
ed into oneDownload the source code, compile and run it. (It is defined as a packageso you should compile and run it as such; IDEs do this without you noticing,but it is useful to know how it is done). Look into theWall.java
code in particular. If you run the program on thecommand-line, and your Terminal supports UTF-8 encoding (all modern ones should, it's just the matter of setting the preferences; UTF-8 encoding is thedefault on our Linux computers in the labs), then the outputshould be a "real" bricky wall to get printed out. If it doesn't, replacethe values of sideBrick
and innerBrick
with " "
and " * "
, correspondingly, to have a "mock"brick wall printed.
% java DonaldTrump 20 15 221Will build a wall 20 wide and 15 tall======================================== ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛ ⬛
Study the main class, DonaldTrump. Replace the reduce
terminal method on forEach
. What shouldyou pass to this method to achieve the effect of wall building? What otherchanges are necessary to make the code compile and run correctly? How thisversion is different from the original one with the reduce
method?Which is betters and why?
collect
, not reduce
Retract the changes in Exercise One. There is another possibility to modify the pipeline, which also collects together the desired results into an aggregate object. This approach involves using the collect(..,..,..)
, 3-argument method, and it is best optimised with respect of an optimal and safe use of mutability when pipeline can be parallelised (We do not consider parallel streams in this study, though!). The collect
method requires three parameters — functions (λ-expressions):
which is similar to the reduction.
R collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner);
To execute the collect
terminal operation, unless we'reusing a standard API container class like ArrayList
, we need to define two methods in the class which we use as an aggregate, in our case the Wall. These two methods are:
void accept()
void combine()
Answer the question "What is the supplier" here? A supplier functional interface has the signature () -> T
; T
is obviouslythe Wall, but it has only one 2-argument constructor — how canwe create a wall with specified width
and height
in such a situation?
Next, add accept
and combine
methods to theWall class; you can make Wall implement java.util.function.BiConsumer
and annotate the method accept
with@Override
, but this is not obligatory — if a rightλ-expression or a method reference is passed, the compiler will make a correct type inference.
You can surely use methods which are already defined in Wall.java
to implement accept
and combine
. If you do this exercise correctly (the amount of additional code you need to write is verysmall, most challenging part is to think this all over!), it would be sufficientto receive the full mark for the homework.
This part is optional.
The streams API provides helper classes to make programming standardpipeline operation easier. The interface java.util.stream.Collector
defines a static default method of(..)
with 3 arguments:
java.util.stream.Collector.of( java.util.function.Suppliersupplier, java.util.function.BiConsumer accumulator, java.util.function.BinaryOperator combiner );
it returns a Collector
object which can be passed to a1-argument collect(Collector c)
method to perform the same task.Add a declaration of a collector variable donaldCollector
to the DonaldTrump.main
body and call Collector.of()
to assign it a value, and thenreplace the 3-argument collect()
which you introduced in the previous Exercise, with a single-argument collect
to which donaldCollector
is passed. The result should be the samewall object like it was in Ex. Two.
Note One Alongside with the 3-argument collect
,the Collector interface also provides a 4-argument version in whichthe fourth term is called finisher, and is used when you need to makea transformation of the final built aggregate into something different. A typical example would be create a string representing all the (relevant)information which is incorporated into a container built by the collect
(the example is from Benjamin Winterberg's ):
Listfamily = Arrays.asList( new Person("Donald", 60), new Person("Melania", 23), new Person("Eric", 32), new Person("Donald Jr.", 39) new Person("Ivanka", 35)); // there're former wives and younger children Collector personNameCollector = Collector.of( () -> new StringJoiner(" | "), // supplier (j, p) -> j.add(p.name.toUpperCase()), // accumulator (j1, j2) -> j1.merge(j2), // combiner StringJoiner::toString); // finisherString names = family .stream() .collect(personNameCollector);System.out.println(names);
Note Two It would a gratuitous exercise to replace a 3-argumentcollect
with a 1-argument one by using a Collector actualargument, because the main benefit of the latter approach is the ability tocompose multiple collectors. You are encouraged to investigate thisapproach further if it interests you, in particular, look into thedocumentation of the java.util.stream.Collectors
utility class.
This part is optional.
Finally, think (and conduct a research if necessary) how to remove aconstraint put in the middle of the stream pipeline(DonaldTrump.main:24
in the original version) to ensure that the stream will terminate when the number of supplied bricks (not balls!) has reached a limit. This limit is set by the user (with the 3d command-line argument), and the assert
statement(DonaldTrump.main:16
) guarantees that the stream pipeline will not go on forever (try running the program with the value of 3d argument exceeding the product of 1st and 2nd, without -ea
option and with it; -ea
enables assertion execution).
Such an a priori constraint is a blemish on our code — weshould not use it because we do not have information about the wall sizebefore the run-time. In a loop-based approach, this is a no-brainer problem— every time a brick is laid into the wall, check if the latter iscomplete, and then "hits the breaks" by calling break
. With astream pipeline, however, this is not so straightforward. Try to come up witha solution. (It's "OK" to look up and find out what other people think, onStackoverflow or else where.) Feel free to discuss you findings on Wattle.
You will get up to two marks, if you present your work at the lab8, Week 12.
HW 6 |
Updated: Sun 12 Jun 2016 17:27:37 AEST • Responsible Officer: JavaScript must be enabled to display this email address. • Page Contact:
+61 2 6125 5111
The Australian National University, Canberra
CRICOS Provider : 00120C ABN : 52 234 063 906