Самый быстрый способ в Java найти конкретное перечисление c, основанное на поиске двух целых чисел - PullRequest
1 голос
/ 11 января 2020

У меня есть следующие три перечисления:

PlayerType

public enum PlayerType {
    NONE (' '),
    BLACK ('b'),
    WHITE ('w');

    private final char _symbol;

    PlayerType(char symbol) {
        _symbol = symbol;
    }

    public char symbol() { return _symbol; }
}

PieceType

public enum PieceType {
    NONE (' '),
    PAWN ('p'),
    KNIGHT ('n'),
    BISHOP ('b'),
    ROOK ('r'),
    QUEEN ('q'),
    KING ('k');

    private final char _symbol;

    PieceType(char symbol) {
        _symbol = symbol;
    }

    public char symbol() { return _symbol; }
}

PlayerPiece

public enum PlayerPiece {
    NONE (PlayerType.NONE, PieceType.NONE),
    BLACK_PAWN (PlayerType.BLACK, PieceType.PAWN),
    BLACK_KNIGHT (PlayerType.BLACK, PieceType.KNIGHT),
    BLACK_BISHOP (PlayerType.BLACK, PieceType.BISHOP),
    BLACK_ROOK (PlayerType.BLACK, PieceType.ROOK),
    BLACK_QUEEN (PlayerType.BLACK, PieceType.QUEEN),
    BLACK_KING (PlayerType.BLACK, PieceType.KING),
    WHITE_PAWN (PlayerType.WHITE, PieceType.PAWN),
    WHITE_KNIGHT (PlayerType.WHITE, PieceType.KNIGHT),
    WHITE_BISHOP (PlayerType.WHITE, PieceType.BISHOP),
    WHITE_ROOK (PlayerType.WHITE, PieceType.ROOK),
    WHITE_QUEEN (PlayerType.WHITE, PieceType.QUEEN),
    WHITE_KING (PlayerType.WHITE, PieceType.KING);

    private final PlayerType _playerType;
    private final PieceType _pieceType;
    private final char[] _symbol;

    private PlayerPiece(
      final PlayerType playerType,
      final PieceType pieceType) {
        _playerType = playerType;
        _pieceType = pieceType;
        _symbol = new char[] {playerType.symbol(), pieceType.symbol()};
    }

    public final PlayerType playerType() { return _playerType; }
    public final PieceType pieceType() { return _pieceType; }
    public final String symbol() { return String.valueOf(_symbol); }
}

Подстановка типа ...

int playerTypeOrdinal = PlayerType.WHITE.ordinal();
int pieceTypeOrdinal = PieceType.QUEEN.ordinal();
PlayerPiece playerPiece = Lookup(playerTypeOrdinal, pieceTypeOrdinal)

... должна возвращать перечисление WHITE_QUEEN PlayerPiece как можно быстрее. Я мог бы использовать для l oop, однако я не уверен, что это самый быстрый подход. Я хочу использовать stati c Map, но не уверен, как использовать два ординала в качестве ключа.

Есть предложения, как это можно сделать эффективно?

РЕШЕНИЕ ОТ ПРИНЯТОГО ОТВЕТА

Это работает, даже в виде шахматного массива, однако существует возможность возникновения исключения ArrayIndexOutOfBoundsException, если я не сделаю их параллельными:

public class PlayerPieceLookup {

    private static final PlayerPiece[][] PLAYER_PIECES = new PlayerPiece[][] {
        {
            PlayerPiece.NONE,
            PlayerPiece.NONE,
            PlayerPiece.NONE,
            PlayerPiece.NONE,
            PlayerPiece.NONE,
            PlayerPiece.NONE,
            PlayerPiece.NONE,
        },
        {
            PlayerPiece.NONE,
            PlayerPiece.BLACK_PAWN, 
            PlayerPiece.BLACK_KNIGHT, 
            PlayerPiece.BLACK_BISHOP, 
            PlayerPiece.BLACK_ROOK, 
            PlayerPiece.BLACK_QUEEN, 
            PlayerPiece.BLACK_KING
        },
        {
            PlayerPiece.NONE,
            PlayerPiece.WHITE_PAWN, 
            PlayerPiece.WHITE_KNIGHT,
            PlayerPiece.WHITE_BISHOP, 
            PlayerPiece.WHITE_ROOK, 
            PlayerPiece.WHITE_QUEEN, 
            PlayerPiece.WHITE_KING
        }       
    };  

    public static void main(String[] args) {
        for(PlayerType player : PlayerType.values()) {
            for(PieceType piece : PieceType.values()) {
                System.out.println("[" + player + "][" + piece + "][" + PLAYER_PIECES[player.ordinal()][piece.ordinal()] + "]");        
            }
        }
    }
 }

Ответы [ 2 ]

2 голосов
/ 11 января 2020

2D массив может сделать это довольно эффективно. Просто заполните массив (например, в блоке c) так, чтобы arr[m][n] был m-ым игроком, n-й частью. поиск будет состоять из двух загрузок массива (поскольку Java 2d массивы являются массивами массивов).

1 голос
/ 11 января 2020

Не используйте ordinal. Это не то, для чего это. По сути, это внутренняя деталь реализации.

Это также не является типобезопасным (что, если вы неправильно вычислите два ординала?).

Посмотрите непосредственно, используя значение перечисления, из EnumMap.

Map<PlayerType, Map<PieceType, PlayerPiece>> map = new EnumMap<>(PlayerType.class);
for (PlayerPiece p : PlayerPiece.values()) {
  map.computeIfAbsent(p.playerType(), k -> new EnumMap<>(PieceType.class))
      .put(p.pieceType(), p);
}

Затем найдите фрагмент, используя:

map.get(playerType).get(pieceType)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...