【问题标题】:How do I "peek" the next element on a Java Scanner?如何“窥视”Java Scanner 上的下一个元素?
【发布时间】:2010-11-26 21:28:33
【问题描述】:

也就是说,如何在不移除迭代器的情况下获取下一个元素?因为我可能想也可能不想删除它,具体取决于它的内容。我有一个文件扫描器,我在其中使用 Scanner next() 方法迭代 XML 标记。

提前致谢。

【问题讨论】:

    标签: java iterator


    【解决方案1】:

    这是另一种基于包装器的解决方案,但这个解决方案只有一个内部扫描器。我留下另一个来展示一个解决方案,这是一个不同的,可能是更好的解决方案。同样,此解决方案并未实现所有内容(并且未经测试),但您只需实现您打算使用的那些部分。

    在此版本中,您将保留对 next() 实际含义的引用。

    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;
        }
    }
    

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        Google Guava 中有一个PeekingIterator,即documented

        【讨论】:

        • Guava 的PeekingIterator 是这里最优雅的解决方案——它速度快,经过充分测试,本质上是解决 OP 问题的单行解决方案。
        • 同意。或 Apache Commons 实现。
        【解决方案4】:

        这是对所有其他人的简单得多的答案。

        我们可以使用match() 方法检索hasNext 的最后一个匹配项,并查看第0 个捕获组(这是正则表达式匹配的整个字符串——正是我们想要的)。

        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"
        

        【讨论】:

          【解决方案5】:

          请参阅this 答案以获得更有效的解决方案。

          这是一个非常丑陋的解决方案,但您可以围绕Scanner 创建一个包装类,它保留两个内部Scanner 对象。您可以通过将第二个扫描仪放在另一个前面来获得peek() 功能

          这是一个非常基本的解决方案(只是为了让您了解我在说什么)并且没有实现您需要的所有内容(但您只需要实现您将使用的那些部分)。 (此外,这是未经测试的,因此请谨慎对待)。

          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;
              }
          }
          

          【讨论】:

          • 我突然想到,您可以在一台扫描仪中执行此操作,只需保留对 next() 对象的引用。
          • 好的,我将该答案添加为另一个答案(我不想简单地将其添加到该答案中,因为我想将其作为一种可能的解决方案来保持)。在某些情况下(如果您使用扫描仪做相当复杂的事情),这可能更容易包装,但另一种解决方案更有效。
          • 请注意,如果字符串为空或仅包含空格,您的 PeekableScanner 构造函数将抛出 NoSuchElementException。
          • 我最终需要这个,因为必须使用 next(RegEx)。使用另一种解决方案,您将获得上次通话中的“下一个”,并将正则表达式的下一个排队等待下一个。 (至少有一个“直截了当”的实现,但是最好抓住这个而不是尝试修复另一个)。
          【解决方案6】:

          如果 Iterator 是 ListIterator,你可以这样做:

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2020-02-06
            • 2023-03-30
            • 2021-12-29
            • 2011-08-06
            • 1970-01-01
            • 2012-01-23
            • 1970-01-01
            相关资源
            最近更新 更多