编程技术文章分享与教程

网站首页 > 技术文章 正文

Java修炼终极指南:183 编写一个用于解析数据的 Function

hmc789 2024-11-16 20:55:57 技术文章 2 ℃

假设我们有以下文本:

String text = """
  test, a, 1, 4, 5, 0xf5, 0x5, 4.5d, 6, 5.6, 50000, 345,
  4.0f, 6$3, 2$1.1, 5.5, 6.7, 8, a11, 3e+1, -11199, 55                     
  """;

目标是从这段文本中仅提取数字。根据给定的场景,我们可能只需要整数,或者只需要双精度浮点数等。有时,我们可能需要在提取之前执行一些文本替换(例如,我们可能想要将 xf 字符替换为点,0xf5 = 0.5)。解决这个问题的一个可能的方案是编写一个方法(我们称之为 parseText()),它接受一个 Function<String, T> 作为参数。Function<String, T> 为我们提供了灵活性,可以形成以下任何一种:

List<Integer> integerValues
  = parseText(text, Integer::valueOf);
List<Double> doubleValues
  = parseText(text, Double::valueOf);
...
List<Double> moreDoubleValues
  = parseText(text, t -> Double.valueOf(t.replaceAll(
      "\\#34;, "").replaceAll("xf", ".").replaceAll("x", ".")));

parseText() 应该执行几个步骤,直到达到最终结果。它的签名可以如下:

public static <T> List<T> parseText(
    String text, Function<String, T> func) {
  ...
}

首先,我们必须通过逗号分隔符分割接收到的文本,并提取项目到一个 String[] 中。这样我们就有访问文本中每个项目的方式。其次,我们可以流式处理 String[] 并过滤任何空项目。第三,我们可以调用 Function.apply() 来对每个项目应用给定的函数(例如,应用 Double::valueOf)。这可以通过中间操作 map() 完成。由于一些项目可能是无效的数字,我们必须捕获并忽略任何异常(像这样忽略异常是一个不好的做法,但在这种情况下,真的没有其他办法)。对于任何无效的数字,我们简单地返回 null。第四,我们过滤所有 null 值。这意味着剩余的流仅包含通过 Function.apply() 的数字。第五,我们将流收集到一个 List 中并返回它。将这 5 个步骤粘合在一起,将得到以下代码:

public static <T> List<T> parseText(
    String text, Function<String, T> func) {
  return Arrays.stream(text.split(",")) // 步骤 1 和 2
    .filter(s -> !s.isEmpty())
    .map(s -> {
       try {
         return func.apply(s.trim());   // 步骤 3
       } catch (Exception e) {}
       return null;
    })
    .filter(Objects::nonNull)           // 步骤 4
    .collect(Collectors.toList());      // 步骤 5
}

完成!你可以使用这个例子来解决广泛的类似的问题。

标签列表
最新留言