java


Error Message in Java (Stream and Lambda Comprehension)


I've been stuck for several hours trying to debug my code.
this is the error message that I get
Error:(8, 8) java: trump.Wall is not abstract and does not override abstract method get() in java.util.function.Supplier
these are the classes that corresponds to that error. So when I run the class DonalTrump it gave me the error message above. And apparently it is because of the Wall class. The following is my code
DonaldTrump
package trump;
import java.util.*;
import java.util.stream.*;
import java.util.function.BiConsumer;
public class DonaldTrump{
public static void main(String[] args) {
if (args.length < 3) {
System.out.println("Need three integer arguments: width height #bricks");
System.exit(1);
}
int width = Integer.parseInt(args[0]);
int height = Integer.parseInt(args[1]);
int numberOfBricks = Integer.parseInt(args[2]);
assert numberOfBricks <= width * height: "Too many bricks";
System.out.printf("Will build a wall %d wide and %d tall%n",
width, height);
System.out.println(String.join("", Collections.nCopies(width,"==")));
Wall trumpWall
= Stream.generate(() -> new Ball(10.0))
.filter(b -> b.colour == Ball.Colour.RED)
.map(Brick::new)
.limit(numberOfBricks)
.collect(() -> new Wall(width, height), Wall::accept, Wall::combine); //UPDATE
System.out.println(trumpWall);
}
}
//Wall SOURCE OF ERROR HERE
package trump;
import java.util.*;
import java.util.function.Supplier;
import java.util.stream.*;
public class Wall implements Supplier<Wall> { //ERROR HERE//
public Wall get() { //UPDATE
return this;
}
private Brick[][] bricks;
private int width;
private int height;
private int lastFilledX;
private int lastFilledY;
private boolean isComplete;
final String sideBrick = "\u2b1b";
final String innerBrick = " \u2b1b"; // black box (brick) in Unicode
public Wall(int w, int h) {
assert w > 0 && h > 0 : "the wall must have finite width and height";
this.width = w;
this.height = h;
this.bricks = new Brick[width][height];
for (int j = 0; j < this.height; j++)
for (int i = 0; i < this.width; i++)
this.bricks[i][j] = null;
this.lastFilledX = 0;
this.lastFilledY = 0;
// this.isComplete = false;
}
public void lay(Brick brick) {
if (this.isComplete()) return;
this.bricks[lastFilledX][lastFilledY] = brick;
// if (this.isComplete()) return false;
if (this.lastFilledX == this.width - 1) {
this.lastFilledX = 0;
this.lastFilledY += 1;
} else {
this.lastFilledX += 1;
}
}
public boolean isComplete() {
return Stream.of(this.bricks).allMatch(
level -> Stream.of(level).allMatch(b -> b != null));
// return (this.lastFilledX == this.width - 1 &&
// this.lastFilledY == this.height - 1);
}
#Override
public String toString() {
StringBuffer buffer = new StringBuffer();
for (int j = this.height - 1; j >= 0; j--) {
for (int i = 0; i < this.width; i++)
// try any from the range u25a2 -- u25a9
buffer.append(bricks[i][j] == null ? " " :
i == 0 ? sideBrick : innerBrick);
// buffer.append(bricks[i][j] == 0 ? "0" : "1");
buffer.append("\n");
}
// return "\033[31m" + buffer.toString() + "\033[0m";
return buffer.toString(); // to hell with color code sequence
}
public static Wall linkTwoWalls(Wall w1, Wall w2) {
assert w1.height == w2.height : "Walls have unequal height";
if (!w1.isComplete() || !w2.isComplete())
return null; //Optional.empty();
int w = w1.width + w2.width;
int h = w1.height;
Brick[][] bricks = new Brick[w][h];
System.arraycopy(w1, 0, bricks, 0, w1.width);
System.arraycopy(w2, w1.width, bricks, 0, w2.width);
Wall result = new Wall(w, h);
result.bricks = bricks;
return result;//Optional.of(result);
}
public static Optional<Wall> joinWalls(Wall... walls) {
if (walls == null || walls.length == 0)
return Optional.empty();
// check all walls are of the same height
int firstHeight = walls[0].height;
Stream<Wall> wallStream = Stream.of(walls);
assert wallStream.allMatch(w -> w.height == firstHeight);
return wallStream.reduce((w1, w2) -> linkTwoWalls(w1, w2));
}
public void accept(Wall wall, Brick brick) { //UPDATE NOT STATIC
wall.lay(brick);
}
public void combine(Wall w1, Wall w2) { //UPDATE NOT STATIC
Wall.linkTwoWalls(w1, w2);
}
public static void main(String[] args) {
Wall wall = new Wall(40, 10);
for (int i = 0; i < 411; i++) {
wall.lay(new Brick(new Ball(10.0)));
if (wall.isComplete())
break;
}
System.out.print(wall);
}
}
At first glance, I see 2 problems with your code:
You are not specifying a Supplier<Wall> in the call to collect in the DonaldTrump class, or you are doing it wrong. It's not correct to make your Wall class implement the Supplier<Wall> interface. Think of it in real life terms: it doesn't make sense that a wall is a supplier of itself. Instead, you should use a lambda expression that matches the Supplier interface, i.e. one that works as if you were implementing the Supplier.get method. This is () -> new Wall(width, height).
In your Wall class, both the accept and combine methods shouldn't be static. Besides, accept should not revceive an instance of Wall, but only accept a Brick, which will be put into this Wall. Also, the combine method should accept only one Wall argument and combine this argument with this Wall. Maybe you could read the lesson about method references in The Java Tutorial, which clearly explains all the different method reference types and when to use each one of them.
Taking these items into account means that you should perform a few changes to your code.
In your DonaldTrump class, place the () -> new Wall(width, height) lambda expression as the Supplier of the collect method:
Wall trumpWall = Stream.generate(() -> new Ball(10.0))
.filter(b -> b.colour == Ball.Colour.RED)
.map(Brick::new)
.limit(numberOfBricks)
.collect(() -> new Wall(width, height), Wall::accept, Wall::combine);
And in your Wall class, change the accept and combine method as follows:
public void accept(Brick brick) { // Lay a brick into THIS wall
this.lay(brick);
}
public void combine(Wall wanother) { // Combine another wall with THIS wall
this.linkToThisWall(another);
}
Where linkToThisWall would be a modified version of your (now useless) linkTwoWalls method:
public void linkToThisWall(Wall another) {
assert this.height == another.height : "Walls have unequal height";
if (!this.isComplete() || !another.isComplete()) {
return; // or maybe throw an exception?
}
int w = this.width + another.width;
int h = this.height;
Brick[][] newBricks = new Brick[w][h];
System.arraycopy(this.bricks, 0, newBricks, 0, this.width);
System.arraycopy(another.bricks, this.width, bricks, 0, another.width);
this.bricks = newBricks;
}
Consider also removing the get method, as implementing Supplier<Wall> is no longer needed.
Actually, with this code fix and refactoring, you no longer need the accept and combine methods. In your DonaldTrump class, you could just use references to the refactored lay and linkToThisWall methods instead:
Wall trumpWall = Stream.generate(() -> new Ball(10.0))
.filter(b -> b.colour == Ball.Colour.RED)
.map(Brick::new)
.limit(numberOfBricks)
.collect(() -> new Wall(width, height), Wall::lay, Wall::linkToThisWall);
EDIT: The main reason for these changes is that you were not using the Stream.collect method correctly.
Stream.collect expects 3 arguments:
A supplier that will be used to create a cumulative, mutable structure where to accumulate the elements of the stream. In your code, this structure is a Wall and the elements of the stream are instances of Brick, so the supplier is () -> new Wall(width, height). This supplier might be seen as an empty wall, i.e. like a place in the ground where to start laying bricks.
An accumulator, which is a BiConsumer that accepts two arguments: the structure returned by the previous item's supplier and an element of the stream. The contract for this accumulator biconsumer is that it has to accumulate one element of the stream into the cumulative, mutable structure. In your case, the cumulative, mutable structure is the Wall created by the supplier above and the elements of the stream are instances of Brick, so the accumulator is Wall::lay, or using a lambda (wall, brick) -> wall.lay(brick). This accumulator might be seen as a worker laying bricks into a wall, one by one.
A combiner, which is a BiConsumer that accepts two arguments, both being instances of a partially filled, mutable structure (these structures have the same type as the structure supplied by the Supplier of item 1). This combiner is to be used when the creation of the final structure can be parallelized, and its contract is to combine (or merge, or mix, or link or join) the second argument structure into the first argument structure. In your case, the partially filled, mutable structures are two Wall instances partially filled with bricks, so the combiner is Wall::linkToThisWall, or using a lambda (leftWall, rightWall) -> leftWall.linkToThisWall(rightWall). All this combining stuff might be seen as two separate workers working in parallel, each one working by laying bricks into his own wall: one worker would start on the left and the other one would start in the right; when they meet in the middle, both half walls are combined into a new full wall.
As to why your solution was incorrect... Your combiner was wrong. You are not supposed to create a new, empty structure and merge the two structures provided as arguments into this new structure. Instead, you should merge the second argument structure into the first argument structure. This is why your static linkTwoWalls method didn't work: you were merging two walls into a new one and you were returning this new wall from that static method. However, that returned wall was being discarded, because the combiner must be a BiConsumer that merges second into first argument. (Yours was actually a BinaryOperator, i.e. you were creating a new wall from two walls and returning it, as when you sum two numbers and get another number as a result). However, you were not using a parallel stream, so your combiner was never used.
You'll need to override the get method of the Supplier interface.
public Wall get(){
return this;
}

Related Links

Spring : XML Configuration Location
Can you make an editable label?
Java equivalent of C#'s 'Enumerable.Any'
Spring MongoDB cascade saving issue
Java: Return unknown generic type in method
Not a JSON Object Exception
Google Search Appliance query request returns 502
Attach Sources - Maven Dependancies [NetBeans]
Pattern / best practice for accessing connection that has undeterministic set time
Not coherent behaviour in switch-case statement in Java7 and Java8
“Missing IN or OUT parameter at index:: 1” when adding ?' parameters to my query [closed]
How to group columns in an SWT table?
Is there a equivalent to JSON.Net in Java? [duplicate]
Images not loading in Web Page
How to open a new jFrame with denied access to the previous jFrame [duplicate]
Apache Cxf different services to different packages

Categories

HOME
clips
webpack
mfc
raspberry-pi
sqlite3
constraint-programming
portia
elasticsearch-hadoop
kentor-authservices
leiningen
zebra-printers
opentracing
telephony
footer
normalizr
text-rendering
jquery-ajaxq
cloudhub
css-animations
devops
android-widget
spark-jobserver
strncpy
publish
opentype
atlassian-crucible
nouislider
winrt-xaml-toolkit
gammu
rotational-matrices
restlet
theano.scan
awt
sfdc
quadratic-programming
node-gyp
nomethoderror
android-mediaprojection
arena-simulation
keydown
midl
convertapi
apple-news
apache-fop
promela
blogengine.net
libusb-win32
windows-mobile-6.5
qtwebview
lync-client-sdk
redundancy
blacklist
smart-table
infix-notation
multi-level
merge-conflict-resolution
xml-attribute
paypal-express
disque
captivenetwork
independentsoft
vhd
mutation-observers
embedded-code
operation
sniffer
sonarqube5.1.2
notify
rake-task
nstableviewcell
tablelayout
nsbutton
flask-cors
project-planning
google-reader
typeof
aapt
rebol3
ember-charts
fmod
runtime.exec
eclipse-memory-analyzer
back-stack
http-unit
zpt
yetanotherforum
oncheckedchanged
android-sdk-2.1
lpeg
filtered-index
preference
nsviewanimation
iweb
libs
commodore

Resources

Encrypt Message



code
soft
python
ios
c
html
jquery
cloud
mobile