如何从ArrayList中提取特定数字?

时间:2018-12-13 05:44:30

标签: java tdd

我编写了一个程序,该程序将从http://worldtimeapi.org/api/ip.txt中获取文本数据,并提取X,其中X是“ unixtime”旁边的值。这就是我到目前为止所得到的。

public class GetDataService implements DataService{
  @Override
  public ArrayList<String> getData()  {
    ArrayList<String> lines = new ArrayList<>();
    try {
    URL url = new URL("http://worldtimeapi.org/api/ip.txt");
    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(url.openStream()));
    String line;
    while ((line = bufferedReader.readLine()) != null) {
      String a = line;
      lines.add(a);
      }
      bufferedReader.close();

    } catch (IOException ex) {
      throw new RuntimeException("Can not making the request to the URL.");
    }
    return lines;
  }

public interface DataService {
  ArrayList<String> getData() throws IOException;
}

public class UnixTimeExtractor {
  private GetDataService getDataService;

  public String unixTimeExtractor()  {
    ArrayList<String> lines = getDataService.getData();
//how to extract the value next to "unixtime"

我不知道如何在“ unixtime”旁边提取值。以及如何测试GetDataService类的NetWork错误。

3 个答案:

答案 0 :(得分:1)

您可以使用indexOf遍历ArrayList并获取下一个值

public String unixTimeExtractor() {
    List<String> lines = getDataService.getData();

    int i = lines.indexOf(unixTime);

    if (i != -1 && ++i < lines.size()) {
        return lines.get(i);
    }
    return null;
}

答案 1 :(得分:1)

  

我不知道如何在“ unixtime”旁边提取值。

要从列表中提取值,可以遍历列表, 根据需要对每个值进行一些检查, 并在找到匹配项时返回该值,例如:

for (String line : lines) {
  if (line.startsWith("unixtime: ")) {
    return line;
  }
}

要提取字符串中“ unixtime:”之后的值,可以使用几种策略:

  • line.substring("unixtime: ".length())
  • line.replaceAll("^unixtime: ", "")
  • line.split(": ")[1]
  • ...

顺便说一句,您真的需要行列表吗? 如果没有,那么在从URL读取输入流时执行此检查,则可以节省内存并减少输入处理, 找到所需的内容后立即停止阅读。

  

以及如何测试GetDataService类的NetWork错误。

要测试是否正确处理了网络错误, 您需要将可引发网络错误的代码部分注入。 然后在测试用例中,您可以注入将引发异常的替换代码, 并验证程序是否正确处理了异常。

一种技术是“提取和扩展”。 也就是说,将url.openStream()调用提取到专用方法:

InputStream getInputStream(URL url) throws IOException {
  return url.openStream();
}

然后用对url.openStream()的调用替换代码getInputStream(url)。 然后在您的测试方法中,可以引发异常来覆盖此方法, 并验证会发生什么。在AssertJ中使用流利的断言:

  @Test
  public void test_unixtime() {
    UnixTimeExtractor extractor = new UnixTimeExtractor() {
      @Override
      InputStream getInputStream(URL url) throws IOException {
        throw new IOException();
      }
    };
    assertThatThrownBy(extractor::unixtime)
      .isInstanceOf(RuntimeException.class)
      .hasMessage("Error while reading from stream");
  }

您可以类似地从输入流中读取内容。

答案 2 :(得分:1)

您可以使用java-8来实现相同的目的。将您的方法更改为以下内容:

public String unixTimeExtractor() {
   ArrayList<String> lines = getDataService.getData();
   return lines.stream().filter(s -> s.contains("unixtime"))
               .map(s -> s.substring("unixtime: ".length()))
               .findFirst()
               .orElse("Not found");
}

在这里,我们在列表lines上进行流式传输,以检查是否找到了 String unixtime。如果找到它,则使用子字符串返回其值,否则返回Not found

对于测试用例,您可以参考janos的答案。