Есть ли способ собрать много многострочных строк, обозначенных определенным символом, в Arraylist, используя поток данных в Java 8?

У меня есть файл fasta, который я хочу разобрать на ArrayList, где каждая позиция имеет целую последовательность. Последовательности представляют собой многострочные строки, и я не хочу включать строку идентификации в сохраняемую строку.
Мой текущий код разбивает каждую строку на другую позицию в ArrayList. Как сделать так, чтобы каждая позиция обозначалась символом >?

Файлы fasta имеют вид:

>identification of a sequence 1
line1
line3
>identification of a sequence 2
line4
>identification of a sequence 3
line5
line6
line7
public static void main(String args[]) {

        String fileName = "fastafile.fasta";
        List<String> list = new ArrayList<>();

        try (Stream<String> stream = Files.lines(Paths.get(fileName))) {

            //1. filter line 3
            //2. convert all content to upper case
            //3. convert it into a List
            list = stream
                    .filter(line -> !line.startsWith(">"))
                    .map(String::toUpperCase)
                    .collect(Collectors.toList());

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

        list.forEach(System.out::println);


    }

Для приведенного выше примера нам нужен такой вывод, что:

System.out.println(list.size()); // this would be 3

System.out.println(list.get(0)); //this would be line1line3

System.out.println(list.get(1)); //this would be line4

System.out.println(list.get(2)); //this would be line5line6line7

person Sam    schedule 27.04.2019    source источник


Ответы (1)


Использование Files.lines, похоже, немного усложняет задачу в зависимости от вашей цели.

Предполагая, что вы можете просто получить все содержимое файла в одном String - следующее работает достаточно хорошо (проверено с помощью онлайн-компилятора ):

import java.util.*;
import java.util.stream.*;


public class Test {
   public static void main(String args[]) {
     String content = ">identification of a sequence 1\n" +
        "line1\n" +
        "line3\n" +
        ">identification of a sequence 2\n" +
        "line4\n" +
        ">identification of a sequence 2\n" +
        "line5\n" +
        "line6\n" +
        "line7";
     List<String> list = new ArrayList<>();
     try {
        list = Arrays.stream(content.split(">.*"))
          .filter(e -> !e.isEmpty())
          .map(e -> e.replace("\n","").trim())
          .collect(Collectors.toList());
     } catch (Exception e) {
         e.printStackTrace();
     }

     list.forEach(System.out::println);

     System.out.println(list.size()); // this would be 3

     System.out.println(list.get(0)); // this would be line1line3

     System.out.println(list.get(1)); // this would be line4

     System.out.println(list.get(2)); // this would be line5line6line7

   }
}

И вывод:

line1line3
line4
line5line6line7
3
line1line3
line4
line5line6line7
person Rann Lifshitz    schedule 28.04.2019
comment
Я бы использовал .replace("\\R",""), чтобы сделать код независимым от конкретной формы последовательности разрыва строки, используемой в файле. Что касается Files.lines, то это скорее работа для Scanner, т.е. см. эти вопросы и ответы. Или посмотрите на этот ответ относительно примера определения строк, начинающихся с определенного токена. Однако здесь шаблон будет намного проще, так как разделитель должен быть использован, например. "^>". - person Holger; 29.04.2019