簡體   English   中英

Java中的錯誤消息(流和Lambda理解)

[英]Error Message in Java (Stream and Lambda Comprehension)

我被困了幾個小時試圖調試我的代碼。

這是我收到的錯誤消息

Error:(8, 8) java: trump.Wall is not abstract and does not override abstract method get() in java.util.function.Supplier

這些是與該錯誤對應的類。 因此,當我運行DonalTrumpDonalTrump它給了我上面的錯誤消息。 顯然是由於Wall類。 以下是我的代碼

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);
    }
}

乍一看,我發現您的代碼有2個問題:

  1. 您沒有在要collectDonaldTrump類的調用中指定Supplier<Wall> ,或者做錯了。 使Wall類實現Supplier<Wall>接口是不正確的。 用現實生活的角度來思考:一堵牆本身就是供應商,這毫無意義。 相反,您應該使用與Supplier接口匹配的lambda表達式,即,該表達式的工作方式就好像您正在實現 Supplier.get方法一樣。 這是() -> new Wall(width, height)

  2. Wall類中, acceptcombine方法都不應該是靜態的。 此外, accept不應revceive的實例Wall ,但只接受一個Brick ,將被放入這個Wall 同樣, combine方法僅應接受一個Wall參數並將此參數與此Wall 也許您可以閱讀The Java Tutorial中有關方法引用的課程 ,該課程清楚地解釋了所有不同的方法引用類型以及何時使用它們中的每一種。

考慮這些因素意味着您應該對代碼進行一些更改。

在您的DonaldTrump類中,將() -> new Wall(width, height) lambda表達式放置為collect方法的Supplier

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);

在您的Wall類中,如下更改acceptcombine方法:

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);
}

其中linkToThisWall將是您的linkTwoWalls方法(現在已無用)的修改版本:

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;
}

考慮也刪除get方法,因為不再需要實現Supplier<Wall>

實際上,通過此代碼修復和重構,您不再需要acceptcombine方法。 DonaldTrump類中,您可以只使用對重構的laylinkToThisWall方法的引用:

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);

編輯:這些更改的主要原因是您沒有正確使用Stream.collect方法。

Stream.collect需要3個參數:

  1. 供應商,該供應商將用於創建累積的可變結構,以在其中累積流的元素。 在您的代碼中,此結構是Wall ,流的元素是Brick實例,因此供應商是() -> new Wall(width, height) 該供應商可能被視為空牆,即像是地面上開始砌磚的地方。
  2. 一個累加器,它是一個BiConsumer ,它接受兩個參數:上一項的供應商返回的結構和流的元素。 此累加器雙消耗者的契約是它必須將流的一個元素累加到累加的可變結構中。 在您的情況下,累積的可變結構是上面的供應商創建的Wall ,而流的元素是Brick實例,因此累加器是Wall::lay或使用lambda (wall, brick) -> wall.lay(brick) 可以將這種蓄能器看作是一名工人一個接一個地將磚砌成的牆壁。
  3. 組合器,它是一個BiConsumer ,它接受兩個參數,兩個參數都是部分填充的可變結構的實例(這些結構的類型與項目1的Supplier提供的結構相同)。 當最終結構的創建可以並行化時,將使用此合並器,並且其合同是將第二個自變量結構合並(或合並,混合,鏈接或聯接)到第一個自變量結構中。 在您的情況下,部分填充的可變結構是兩個用磚塊部分填充的Wall實例,因此組合器是Wall::linkToThisWall ,或者使用lambda (leftWall, rightWall) -> leftWall.linkToThisWall(rightWall) 所有這些結合在一起的東西可能被看作是兩個獨立的工人並行工作,每個工人都在自己的牆壁上砌磚工作:一個工人從左邊開始,另一個工人從右邊開始; 當它們在中間相遇時,兩個半牆合並為一個新的全牆。

至於為什么您的解決方案不正確...您的組合器是錯誤的。 您不應該創建一個新的空結構,並將作為參數提供的兩個結構合並到這個新結構中。 相反,您應該將第二個參數結構合並到第一個參數結構中。 這就是為什么您的靜態linkTwoWalls方法不起作用的原因:您將兩堵牆合並為新的牆,並且從該靜態方法返回了這堵新牆。 但是,返回的牆已被丟棄,因為合並器必須是將第二個合並到第一個參數中的BiConsumer (您實際上是BinaryOperator ,即您是從兩個牆中創建一個新牆並將其返回,就像您將兩個數字求和並得到另一個數字一樣)。 但是,您沒有使用並行流,因此從未使用過合並器。

您將需要覆蓋Supplier接口的get方法。

public Wall get(){
      return this;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM