Как добавить объекты в 2D-массив на основе символов во входном файле с помощью Java Stream - PullRequest
3 голосов
/ 12 апреля 2019

Я читаю входные данные из файла, где каждая строка имеет одинаковое количество символов.

o o t o o o o o o o

o o o o o o o T o o

r r r o o o o T o o

r r r r o o o o o o

r r r r r t o o o o

Я пытаюсь добавить объекты в двухмерный массив типа Square [] [].Square - это интерфейс с несколькими реализациями, такими как SquareOne, SquareTwo, SquareThree и т. Д.

Где бы в файле не было 'o', я намерен добавить объект SquareOne для этого местоположения.Аналогично SquareTwo для «t», SquareThree для «r» и так далее.Например, у квадрата [0] [0] должен быть объект SquareOne, тогда как у [0] [2] должен быть объект SquareTwo.

Как мне добиться этого с помощью потока Java 8?

дойти до чтения символов этого файла и добавления их всех в массив char [] [].Но вместо этого я хочу добавить объекты на основе символа в Square [] [].

 public static char[][] addFromFileToSquareArray(String filePath){
        char[][] doubleChar = new char[5][10];
        try (Stream<String> stream = Files.lines(Paths.get(filePath))) {
           doubleChar =  stream
                         .map(x->x.replaceAll(" ",""))
                         .map(String::toCharArray).toArray(char[][]::new);

        } catch (IOException e) {
            e.printStackTrace();
        }
        return doubleChar;
    }

1 Ответ

5 голосов
/ 12 апреля 2019

Один из подходов заключается в потоковой передаче по символам каждой строки, например

public static Square[][] addFromFileToSquareArray(String filePath) {
    Square[][] squares;
    try(Stream<String> stream = Files.lines(Paths.get(filePath))) {
        squares = stream
            .filter(line -> !line.isEmpty())
            .map(line -> line.chars()
                .filter(ch -> ch != ' ')
                .mapToObj(ch -> ch =='o'? new SquareOne():
                          ch == 't'? new SquareTwo(): new SquareThree())
                .toArray(Square[]::new) )
            .toArray(Square[][]::new);
    } catch(IOException e) {
        throw new UncheckedIOException(e);
    }
    return squares;
}

Как правило, я бы предпочел объявить throws IOException в методе, чтобы заставить вызывающую сторону разумно обрабатывать потенциальные исключения,По крайней мере, вы не должны перехватывать исключения, просто печатать их и возвращать значение результата, которое позже вызовет другие проблемы (например, неинициализированный массив, как в исходном коде).

Поскольку отображение, по-видимому,чтобы быть расширяемым, стоит перенести его в собственный метод, например

public static Square squareFor(int type) {
    switch(type) {
        case 'o': return new SquareOne();
        case 't': return new SquareTwo();
        case 'r': return new SquareThree();
        default: throw new IllegalArgumentException("type "+(char)type);
    }
}

и использовать

public static Square[][] addFromFileToSquareArray(String filePath) {
    Square[][] squares;
    try(Stream<String> stream = Files.lines(Paths.get(filePath))) {
        squares = stream
            .filter(line -> !line.isEmpty())
            .map(line -> line.chars()
                .filter(ch -> ch != ' ')
                .mapToObj(Square::squareFor)
                .toArray(Square[]::new) )
            .toArray(Square[][]::new);
    } catch(IOException e) {
        throw new UncheckedIOException(e);
    }
    return squares;
}

Я поместил метод squareFor прямо вSquare интерфейс.В противном случае вы должны изменить класс в справочнике Square::squareFor.

В качестве альтернативы вы можете использовать Map

public static Square[][] addFromFileToSquareArray(String filePath) {
    Square[][] squares;
    Pattern spaces = Pattern.compile(" ");
    try(Stream<String> stream = Files.lines(Paths.get(filePath))) {
        squares = stream
            .filter(line -> !line.isEmpty())
            .map(line -> spaces.splitAsStream(line)
                .map(Square::squareFor)
                .toArray(Square[]::new) )
            .toArray(Square[][]::new);
    } catch(IOException e) {
        throw new UncheckedIOException(e);
    }
    return squares;
}
static final Map<String,Supplier<Square>> MAP = Map.of(
    "o", SquareOne::new,
    "t", SquareTwo::new,
    "r", SquareThree::new
);
public static Square squareFor(String type) {
    Supplier<Square> s = MAP.get(type);
    if(s == null) throw new IllegalArgumentException("type "+type);
    return s.get();
}

Здесь строка разбивается на подстрокииспользует пробелы в качестве разделителя, который по сути их устраняет, поэтому в дальнейшем не требуется операция filter.Но ваша жизнь была бы намного проще, если бы вы могли переопределить свой формат ввода, чтобы не содержать эти пробелы.

...