【问题标题】:How to check if a string is a number [duplicate]如何检查字符串是否为数字[重复]
【发布时间】:2011-11-27 16:33:01
【问题描述】:

我在 Core Java 中有转换为 Map 的问题。

以下是要求:
下面给定一个字符串数组

String str[] = {"abc","123","def","456","ghi","789","lmn","101112","opq"};          

将其转换为 Map 以使结果输出低于

输出

====== ======
核心价值
====== ======
abc 真
123 错误
默认为真
456 错误

应该为数组中的每个元素打印上述内容。我已经编写了代码,但它不工作,我被卡住了。请让我知道如何解决。提前致谢。

import java.util.HashMap;       
import java.util.Iterator;       
import java.util.Map;       

public class CoversionToMap {

/**
 * @param args
 */
public static void main(String[] args) {
    String str[] = {"abc","123","def","456","ghi","789","lmn","101112","opq"};
    Map m = new HashMap();
    for(int i=0;i<str.length;i++){
        if(Integer.parseInt(str[i]) < 0){
            m.put(str[i],true);
        }else{
            m.put(str[i],false);
        }
    }
    //Print the map values finally
    printMap(m);
}   

public static void printMap(Map mp) {
        Iterator it = mp.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry pairs = (Map.Entry)it.next();          
            System.out.println(pairs.getKey() + " = " + pairs.getValue());
        }
}  
}           

例外:

线程“main”中的异常 java.lang.NumberFormatException:对于输入字符串:“abc” 在 java.lang.NumberFormatException.forInputString(未知来源) 在 java.lang.Integer.parseInt(未知来源) 在 java.lang.Integer.parseInt(未知来源) 在 CoversionToMap.main(CoversionToMap.java:22)

【问题讨论】:

  • 你有输出吗?你有错误吗?
  • 更新了@talnicolas,伙计们我真的被困住了,没有任何帮助。我终于来到这里需要你的帮助。
  • 数字只需要与 false 相关联还是只是一个交替的东西?
  • 看一下 Integer.parseInt 的 javadoc 怎么样?如果每个非数字字符串在解析时都给出负数,你将如何解析负数?见download.oracle.com/javase/6/docs/api/java/lang/…。标准 API 中有数千种方法。您将无法猜测他们每个人的作用。阅读他们的文档是了解他们做什么以及如何工作的方式。
  • 字母为真,数字为假;

标签: java arrays hashmap


【解决方案1】:

这是一种更通用的验证方法、避免异常以及使用 Format 子类已知的内容。例如 SimpleDateFormat 知道 2 月 31 日是无效的,只要你告诉它 not 要宽容。

import java.text.Format;
import java.text.NumberFormat;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;

public class ValidatesByParsePosition {

    private static NumberFormat _numFormat = NumberFormat.getInstance();
    private static SimpleDateFormat _dateFormat = new SimpleDateFormat(
            "MM/dd/yyyy");

    public static void printMap(Map<String, Boolean> map) {

        for (Map.Entry<String, Boolean> entry : map.entrySet()) {
            System.out.println(entry.getKey() + " = " + entry.getValue());
        }
    }

    public static void main(String[] args) {

        System.out.println("Validating Nums with ParsePosition:");
        String numStrings[] = { "abcd", "123", "101.112", "-1.54774", "1.40t3" };
        Map<String, Boolean> rslts = new HashMap<String, Boolean>();
        for (String s : numStrings) {
            rslts.put(s, isOk(_numFormat, s));
        }
        ValidatesByParsePosition.printMap(rslts);

        System.out.println("\nValidating dates with ParsePosition:");
        String dateStrings[] = { "3/11/1952", "02/31/2013", "03/14/2014", 
                "05/25/2014", "3/uncle george/2015" };
        rslts = new HashMap<String, Boolean>();
        _dateFormat.setLenient(false);
        for (String s : dateStrings) {
            rslts.put(s, isOk(_dateFormat, s));
        }
        ValidatesByParsePosition.printMap(rslts);
    }

    public static boolean isOk(Format format, String str) {

        boolean isOK = true;
        int errorIndx = -1;
        int parseIndx = 0;

        ParsePosition pos = new ParsePosition(parseIndx);

        while (isOK && parseIndx < str.length() - 1) {
            format.parseObject(str, pos);
            parseIndx = pos.getIndex();
            errorIndx = pos.getErrorIndex();
            isOK = errorIndx < 0;
        }

        if (!isOK) {
            System.out.println("value \"" + str
                    + "\" not parsed; error at char index " + errorIndx);
        }

        return isOK;
    }

}

【讨论】:

    【解决方案2】:

    Integer.parseInt(..) 抛出无效输入异常。

    您的if 子句应如下所示:

    if (isNumber(str[i])) {
       ...
    } else {
       ...
    }
    

    isNumber 可以通过多种方式实现。例如:

    • 使用try { Integer.parseInt(..) } catch (NumberFormatException ex)(参见this相关问题)
    • 使用 commons-lang NumberUtils.isNumber(..)

    【讨论】:

    • 我不希望 NumberUtils 函数如何在 Java 中完成。
    • 然后使用第一个选项
    • 通过使用 NumberUtils,您将获得经过良好测试的快速实现,比您自己未经测试的代码更好。
    • @Deepak - 你有,但显然有人有我 -1。我想知道他认为哪一部分是错误的
    • @EJP 因为那是他的问题,这就是它“不起作用”的原因。程序员不只是发布“它不起作用”,他们发布异常/错误。然后他更新了问题,顺便说一句,所以我会删除注释
    【解决方案3】:

    这是一个改进的答案,可用于负值、小数点等数字。它使用Regular Expressions

    在这里:

    public class StringValidator {
    
        public static void printMap(Map<String, Boolean> map) {
            Iterator it = map.entrySet().iterator();
            for(Map.Entry<String, Boolean> entry:map.entrySet()){
                System.out.println(entry.getKey()+" = "+ entry.getValue());
            }
        }
    }
    
    class ValidateArray{
            public static void main(String[] args) {
            String str[] = {"abcd", "123", "101.112", "-1.54774"};
            Map<String, Boolean> m = new HashMap<String, Boolean>();
            for (String s : str) {
                m.put(s, isNumber(s));
            }
            StringValidator.printMap(m);
        }
    
        public static boolean isNumber(String str) {
            Pattern pattern = Pattern.compile("^-?\\d+\\.?\\d*$");
            Matcher matcher = pattern.matcher(str);
            return matcher.matches();
        }
    }
    

    【讨论】:

      【解决方案4】:

      我想在这里输入关于“不使用异常处理”的相反观点。以下代码:

      try
      {
        InputStream in = new FileInputStream(file);
      }
      catch (FileNotFoundException exc)
      {
        // ...
      }
      

      完全等同于:

      if (!file.exists())
      {
        // ...
      }
      else
      try
      {
        InputStream in = new FileInputStream(file);
      }
      catch (FileNotFoundException exc)
      {
       // ...
      }
      

      前一种情况除外:

      1. 文件是否存在只检查一次
      2. 在两次检查之间没有时间窗口可以改变事情。
      3. // ... 处的处理只编程一次。

      所以你看不到第二种情况的代码。至少你不应该。

      目前的情况是相同的,只是因为它是String,所以没有时间窗口。 Integer.parseInt() 无论如何都必须检查输入的有效性,并且它会抛出一个异常,无论如何都必须在某个地方捕获该异常(除非您喜欢 RTE 停止您的线程)。那么为什么每件事都做两次呢?

      您不应该将异常用于正常流控制的反驳论点只是提出了问题。 正常的流量控制吗?还是输入错误? [事实上,我一直将此原则理解为在方法中更具体地表示“不要向您自己的代码抛出异常”,即使这样,在极少数情况下它也是最佳答案。我不喜欢任何形式的笼统规则。]

      ObjectInputStream 上检测 EOF 的另一个示例。你可以通过捕捉EOFException 来做到这一点。除了在流中添加计数前缀之外没有其他方法,这是设计更改和格式更改。那么,EOF 是正常流程的一部分,还是例外?鉴于它通过异常报告,它如何成为正常流程的一部分?

      【讨论】:

      • @downvoter 请解释一下。否则,特别是除非您解决我在这里提出的论点,否则您只是在说服我和其他所有人,这种“不要使用异常来控制流量”的东西只是一个未经审查且站不住脚的教条。
      • 不是我,但可能因为它与操作原始问题完全无关,而是我在其他地方制作的 cmets。尝试在谷歌上搜索“java异常流控制”以获取大量最佳实践建议,或者只查看stackoverflow.com/questions/1546514/…我已经对你的帖子发表了评论,但不想再被拖入其中,我有工作要做做。
      • 这又一次引出了一个问题,即它是否真的最佳实践,或者仅仅是一个未经检验的教条,其最初的动机已在时间的迷雾中被遗忘:但是不是我,因为当时我就在身边。我打开文件的论点仍然完全没有得到解决,由于我在此处所述的原因,该示例也是无可争辩的最佳实践。
      【解决方案5】:

      假设您不使用任何外部库,您也可以使用正则表达式匹配器来执行此操作。就像

      for (String element : str) {
           m.put(element, element.matches("\\d+"));
      }
      

      请注意,这仅适用于非负整数,但您可以调整正则表达式以匹配您想要映射为 true 的数字格式。另外,如果元素是null,你会得到一个NullPointerException,所以这里需要一点防御代码。

      【讨论】:

        【解决方案6】:

        每个人都建议为此使用异常处理,这里没有什么异常可以保证使用这样的异常,你不要尝试在你的车里左转,如果你撞车了,你会向右转吗?这样的事情应该这样做

        Map<String, Boolean> m = new HashMap<String, Boolean>();
        for (String str: strs) {
            m.put(str, isInteger(str));
        }
        
        public boolean isInteger(String str) {
            int size = str.length();
        
            for (int i = 0; i < size; i++) {
                if (!Character.isDigit(str.charAt(i))) {
                    return false;
                }
            }
        
            return size > 0;
        }
        

        比捕获抛出异常更清晰、更高效,即使有 99% 的整数,因为甚至不需要整数值,因此不需要转换。

        【讨论】:

        • 您可能希望在开头添加一个减号检查
        • true,但除此之外是一个不错的解决方案 (+1)。但我会让isInteger() static
        • 是的,但是您不妨首先使用 Commons / Lang :-)
        • 如何更好? 无论如何,您必须捕获异常。
        • -1 这绝对没有比使用异常处理的更短、更清晰的版本更清晰。与您的理解相反,异常不仅适用于“崩溃”情况,而且是一种有效且可接受的编程方法。此外,由于 parseInt() 保证 String 可以被解析,而你的不能,它更易于维护。
        【解决方案7】:
        boolean intVal = false;
            for(int i=0;i<str.length;i++) {
                    intVal = false;
                    try {
                        if (Integer.parseInt(str[i]) > 0) {
                            intVal = true;
                        }
                    } catch (java.lang.NumberFormatException e) {
                        intVal = false;
                    }
                m.put(str[i], !intVal);
            }
        

        【讨论】:

        • 我的反对意见也一样...只是想提供帮助!
        • 可能出于同样的原因,我对其他人投了反对票,这与某些计数在其他人也反对票的情况下变为负数的方式不同,它使用异常处理来进行逻辑检查。我没有否决在我的回答之后出现并且没有发表评论的这个特定的一个或其他一些人,如果我添加了一个答案,那将是错误的
        【解决方案8】:

        如果要检查字符串是否为有效的 Java 编号,可以使用 org.apache.commons.lang.math 中的方法 isNumber(此处的文档:http://commons.apache.org/lang/api-2.4/org/apache/commons/lang/math/NumberUtils.html)。

        这样您就不必编写自己的 isNumber 实现

        【讨论】:

          【解决方案9】:

          您的错误发生在这里:

          if(Integer.parseInt(str[i]) < 0){
          

          当输入不是数字时,Integer.parseInt 会抛出 NumberFormatException,因此需要使用 try/catch 块,例如:

          try{
              int number = Integer.parseInt(str[i]);
              m.put(str[i],false);
          }catch NumberFormatException nfe{
              m.put(str[i],true);
          }
          

          【讨论】:

          • 滥用异常处理,请原谅我对此进行了一些说明,但这是错误的,完全错误的,预计这些字符串并不总是字符串
          • @vickirk 这是错误的,但最终并没有那么错。如果您没有提供实用方法,那是 Integer 类的设计者的问题,而不是您的问题。他们没有给你一个验证实用程序而不是例外,他们应该有。因此,您只需使用他们的验证实用程序,不幸的是,这是一个例外。
          • 这不是滥用异常处理,而是该方法的预期用途。我假设这个微不足道的例子确实微不足道,并且发布者会打算使用他们认为是整数的值,在这种情况下,无论如何你都必须捕获异常。
          【解决方案10】:

          用调用 isInteger(str[i]) 替换您的 parseInt 行,其中 isInteger 定义为:

          public static boolean isInteger(String text) {
            try {
              new Integer(text);
              return true;
            } catch (NumberFormatException e) {
              return false;
            }
          }
          

          【讨论】:

          • 只是使用异常处理进行逻辑处理的另一种变体
          【解决方案11】:

          您检查parseInt 是否返回小于0 的数字以查看输入是否为非数字。

          但是,如果输入为非数字,则该方法根本不会返回任何值。如您所见,它会抛出 an exception

          做你想做的最简单的方法是捕捉那个异常并采取相应的行动:

          try {
            Integer.parseInt(str[i]);
            // str[i] is numeric
          } catch (NumberFormatException ignored) {
            // str[i] is not numeric
          }
          

          【讨论】:

          • 为什么人们建议这样做。不管是不是数字都是这个过程的正常部分,不是异常也不是错误。以这种方式使用异常处理是错误的,考虑到 50% 的时间可能会发生这种情况,效率会很低
          • @vickirk:人们建议这样做是因为 Java API 在这方面很糟糕,并且没有简单的方法来检查“这是否可解析为 int”而不进行异常处理。是的,第三方库会这样做,但是当你还在学习时,这并不重要。
          • 我认为找出一种简单的方法来检查字符串是否包含数字是非常简单的任务,非常适合学习,而不是从一开始就养成坏习惯。
          • @vickirk:可能。但在您这样做之前,您必须先了解为什么发布的代码不起作用。
          • @EJB,因为异常处理很昂贵,尽管人们有 sadi 很难理解,如果我正在查看代码试图弄清楚它的作用,我不需要查看异常处理,这是针对异常情况的,即错误,我会在知道它在做什么之后再看,很多人使用折叠编辑器来隐藏该代码以进行一般浏览/编辑。事实上有一个例外,因为调用者认为字符串可能不是数字,但在这种情况下,我们知道它不会出现在 50% 的情况下,几乎没有例外。
          【解决方案12】:

          您需要使用 try/catch 块而不是测试 parseInt 的返回值。

          try {
              Integer.parseInt(str[i]);
              m.put(str[i],true);
          } catch(NumberFormatException e) {
              m.put(str[i],false);
          }
          

          【讨论】:

          • 应避免使用 try catch 作为常规流控制,最好进行正则表达式检查
          • @vickirk 但是它是常规的流量控制吗?还是它在处理错误情况?
          • @EJP 常规控制是一个 if else 语句,这是使用提供的错误处理机制来捕获并从该错误中恢复,如果您不知道有多少在您的帐户,您会在决定用信用卡付款之前让银行退回支票吗?甚至没有使用 parseInt 的返回值这一事实表明有些事情是不对的。任何自动代码验证都会报告这一点,这将导致许多人的 QA 过程失败
          猜你喜欢
          • 2016-02-18
          • 2012-12-21
          • 2021-07-10
          • 1970-01-01
          • 2012-03-26
          • 1970-01-01
          • 2012-04-21
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多