简体   繁体   中英

How do I “peek” the next element on a Java Scanner?

That is, how do I get the next element of the iterator without removing it? As I may or may not want to remove it depending on its content. I have a file scanner where I iterate over XML tags using the Scanner next() method.

Thanks in advance.

Here is another wrapper based solution, but this one has only one internal scanner. I left the other up to show one solution, this is a different, and probably better solution. Again, this solution doesn't implement everything (and is untested), but you will only have to implement those parts that you intend to use.

In this version you would keep around a reference to what the next() actually is.

import java.util.Scanner;

public class PeekableScanner
{
    private Scanner scan;
    private String next;

    public PeekableScanner( String source )
    {
        scan = new Scanner( source );
        next = (scan.hasNext() ? scan.next() : null);
    }

    public boolean hasNext()
    {
        return (next != null);
    }

    public String next()
    {
        String current = next;
        next = (scan.hasNext() ? scan.next() : null);
        return current;
    }

    public String peek()
    {
        return next;
    }
}

我不认为有类似 peek 的方法,但是您可以使用hasNext(String)来检查下一个令牌是否是您要查找的。

Google Guava 中记录了一个PeekingIterator

See this answer for a more efficient solution.

This is a very ugly solution, but you can create a wrapper class around Scanner which keeps two internal Scanner objects. You can get peek() functionality by having the second scanner one ahead of the other

This is a very basic solution (just to give you an idea of what I'm talking about) and doesn't implement all that you would need (but you would only need to implement those parts you would use). (also, this is untested, so take it with a grain of salt).

import java.util.Scanner;

public class PeekableScanner
{
    private Scanner scan1;
    private Scanner scan2;
    private String next;

    public PeekableScanner( String source )
    {
        scan1 = new Scanner(source);
        scan2 = new Scanner(source);
        next = scan2.next();
    }

    public boolean hasNext()
    {
        return scan1.hasNext();
    }

    public String next()
    {
        next = (scan2.hasNext() ? scan2.next() : null);
        return scan1.next();
    }

    public String peek()
    {
        return next;
    }
}

Here's a much simpler answer to all the others.

We can use the match() method to retrieve the last match of hasNext , and look at the 0th capture group (which is the entire string matched by the regex --- exactly what we want).

Scanner s = ​new Scanner("a\nb")​​​​​​;

s.hasNext(".*"); // ".*" matches anything, similar to hasNext(), but updates the scanner's internal match variable
s.match().group(0)​;​ // returns "a"

s.next() // returns "a"

If the Iterator is a ListIterator you can do something like this:

if(it.hasNext()) {
   if(it.next() ... 
   it.previous();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM