2016-01-28 10 views
5
public final Pattern PATTERN = Pattern.compile("<abc:c\\sabc:name=\"(\\S+)\"\\sabc:type=\"(\\S+)\">"); 
    try (Stream<String> stream = Files.lines(template.getPath())) { 
     stream.filter(s -> PATTERN.matcher(s).find()).forEach(System.out::println); 

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

Il modello funziona correttamente ma come posso catturare/ottenere i miei gruppi? Al momento ricevo solo stringhe.Applicare il modello al flusso di file

+2

Può questo modello apparire più di 1 volta in una riga? – Tunaki

+0

Non lo so esatcly ma io cosa - sì;) – Tobias

+2

'.filter (s -> PATTERN.matcher (s) .find())' è equivalente a '.filter (PATTERN.asPredicate())' ... – Holger

risposta

7

Se il motivo che si sta applicando appare solo una volta per una linea, è possibile mappare lo Stream<String> in un Stream<Matcher>, filtrare le linee che corrispondono al modello ed infine estrarre il gruppo 1 e 2 memorizzandole in un array.

try (Stream<String> stream = Files.lines(Paths.get(""))) { 
    stream.map(PATTERN::matcher) 
      .filter(Matcher::find) 
      .map(m -> new String[] { m.group(1), m.group(2) }) 
      .forEach(a -> System.out.println(Arrays.toString(a))); 
} catch (IOException e) { 
    e.printStackTrace(); 
} 

Se il modello appare più di una volta, avremmo bisogno di un loop all'interno di Matcher fino find() rendimenti false. In questo caso, potremmo avere

try (Stream<String> stream = Files.lines(Paths.get(""))) { 
    stream.map(PATTERN::matcher) 
      .flatMap(m -> { 
       List<String[]> list = new ArrayList<>(); 
       while (m.find()) { 
        list.add(new String[] { m.group(1), m.group(2) }); 
       } 
       return list.stream(); 
      }) 
      .forEach(a -> System.out.println(Arrays.toString(a))); 

In Java 9, ci può essere un nuovo metodo per recuperare un Matcher.results()Stream<MatchResult> dei risultati. Potremmo usarlo qui invece di avere 2 operazioni separate find e group.

+5

Inoltre (solo Java 9) vedere ['Scanner.findAll()'] (http://download.java.net/jdk9/docs/api/java/util/Scanner.html#findAll-java.util.regex.Pattern -) per ottenere un 'Stream '. Uno scanner può leggere direttamente il file, evitando la lettura basata sulla linea e le sue limitazioni. –

+1

@StuartMarks Aggiunta molto comoda! Non lo sapevo, grazie per averlo presentato. – Tunaki

+1

Il nidificato 'forEach' sembra brutto. Utilizzare 'flatMap' per il passaggio precedente. Quindi potresti sostituire 'List' con' Stream.Builder' che è potenzialmente più efficiente. – Holger

Problemi correlati