在JAVA中动态确定用户输入数据类型

Kai*_*nix 9 java json

我编写了以下代码来确定用户输入的输入的数据类型.

更新:删除解析,Float因为Double也可以Float按照@DodgyCodeException提到的某些精度来解析值

import java.util.Scanner;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class Main {

    public static void main(String[] args) {
        Scanner src = new Scanner(System.in);
        String input;
        System.out.println("Enter input:");
        input = src.nextLine();
        System.out.println("You entered:" + getDataType(input));
    }

    private static String getDataType(Object input) {
        try {
            JSONObject obj = new JSONObject((String) input);
            return "JSONObject";
        } catch (JSONException ex) {
            try {
                JSONArray array = new JSONArray(input);
                return "JSONArray";
            } catch (JSONException ex0) {
                try {    
                    Integer inti = Integer.parseInt((String) input);
                    return "Integer";
                } catch (NumberFormatException ex1) {
                    try {                          
                            Double dub = Double.parseDouble((String) input);
                            return "Double";
                        } catch (NumberFormatException ex3) {
                            return "String";
                        }
                    }
                }
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我要反复运行数百次,而且我读过捕捉Exception是一项昂贵的操作.
有没有更好的方法来实现这一目标?

Hen*_*sen 7

我的方法是让框架做它的事情,并用它来解析输入的通用方式:

Object obj = new org.json.JSONTokener(input).nextValue();
if (obj instanceof JSONArray)
    return "JSONArray";

if (obj instanceof JSONObject)
    return "JSONObject";

if (obj instanceof Integer)
    return "Integer"
...
Run Code Online (Sandbox Code Playgroud)

也许使用switch语句或Map代替一长串if构造.并捕获JSONException无效JSON的输入.

也许可以简化为返回obj.getClass()或obj.getClass().getSimpleName()几乎相同的功能,你现在拥有.


And*_*lko 5

老实说,我不喜欢通过解析器的异常来确定类型的想法.我将为每种格式构建一个模式,并迭代所有格式以检查给定的字符串是否匹配其中一个.

这与Scanner班级的工作方式类似,但它非常复杂.编写应涵盖所有可能情况的正则表达式很困难.

但是如果准备好了正则表达式,算法很简单:

public class Main {

    private final Map<String, String> patterns = Map.of(
            "Integer", integerPattern()
    );

    public String getDataType(String input) {
        for (Map.Entry<String, String> entry : patterns.entrySet()) {
            if (Pattern.matches(entry.getValue(), input)) {
                return entry.getKey();
            }
        }
        return "Unknown";
    }

}
Run Code Online (Sandbox Code Playgroud)

这是一个有趣的部分 - 一个例子integerPattern().我已经取消了它Scanner并简化了一下:

private String integerPattern() {
    String radixDigits = "0123456789abcdefghijklmnopqrstuvwxyz".substring(0, 10);
    String digit = "((?i)[" + radixDigits + "]|\\p{javaDigit})";
    String groupedNumeral = "(" + "[\\p{javaDigit}&&[^0]]" + digit + "?" + digit + "?(" +
            "\\," + digit + digit + digit + ")+)";
    String numeral = "((" + digit + "++)|" + groupedNumeral + ")";
    String javaStyleInteger = "([-+]?(" + numeral + "))";
    String negativeInteger = "\\-" + numeral + "";
    String positiveInteger = "" + numeral + "";
    return "(" + javaStyleInteger + ")|(" +
            positiveInteger + ")|(" +
            negativeInteger + ")";
}
Run Code Online (Sandbox Code Playgroud)

我很确定你可以谷歌所有的正则表达式或在这里找到它们.

但是,如果有一个"更轻"的解决方案或者您根本不想使用正则表达式方法呢?

您可以通过以下方式混合使用不同的技术Map<String, Predicate<String>>:

class Main {

    private final Map<String, Predicate<String>> predicates = Map.of(
            "Integer", this::isInteger,
            "JSON", this::isJSON
    );

    public String getDataType(String input) {
        for (Map.Entry<String, Predicate<String>> predicate : predicates.entrySet()) {
            if (predicate.getValue().test(input)) {
                return predicate.getKey();
            }
        }
        return "Unknown";
    }

    private boolean isJSON(String input) {
        return LibraryClass.isJSON(input);
    }

    private boolean isInteger(String input) {
        try {
            Integer.valueOf(input);
        } catch (NumberFormatException e) {
            return false;
        }
        return true;
    }

}
Run Code Online (Sandbox Code Playgroud)

我相信它更具可读性,它降低了嵌套级别,并在不同的方法中封装了不同的逻辑.

  • 正则数据总是一种"更好"的方法来确定这一点,但不会产生与上述相同的结果,并且在许多情况下可能会更慢 - 我认为值得澄清,因为最初的问题集中在性能上. (3认同)