繁体   English   中英

编写此方法最有效的方法是什么?

[英]What's the most efficient way to write this method?

该方法返回一个“成分”object,它是根据配方 txt 文件中的给定行构建的。 注意: InvalidIngredientException类似于InputMismatchExceptionIngredient版本。 这不是由给定配方文件中的任何行抛出的。

public static Ingredient parseString(String line)
        throws InvalidIngredientException {        
    double quantity = 1;
    String measurement = "";
    String[] parts = line.split(";");
    if (parts.length == 1) {
        throw new InvalidIngredientException(EXP_MSG);
    }
    if (!parts[0].trim().isEmpty()
            && !(Double.parseDouble(parts[0]) == 1)) {
        quantity = Double.parseDouble(parts[0].trim());
    }
    if (!parts[1].trim().isEmpty()) {
        measurement = parts[1].trim();
    } 
    return new Ingredient(quantity, measurement, parts[2].trim());
}

配方文件如下所示:

Cranberry Oatmeal Chews
8; tablespoon; butter
2; tablespoon; oil
1; cup; light brown sugar
1; ; zest of one orange
6; tablespoon; sour cream
2; teaspoon; vanilla
1.5; cup; flour
.5; teaspoon; baking soda
1; teaspoon; cinammon
.5; teaspoon; salt
2; cup; oats
1.5; cup; dried cranberries
.5; cup; walnuts

该方法有效,但我觉得它可以使用更少的代码。

您正在尝试做的事情称为“将 CSV 行绑定到一个对象”。 有很多不错的库可以解析 CSV,大多数成熟的库也提供绑定功能。 还有基于注释的代码生成启用框架,如 Lombok 或 Jackson,它使 Java 更接近方便的语言,如 Scala,使您免于手动编写非常冗长的 getters/setters(构建过程可能有点复杂) .

一旦你使用了正确的搜索词,你就会发现大量的例子。 一个做我上面描述的就是这个,下面是一个根据你的命名调整的版本。 它正在使用 Jackson。

带有 Jackson 注释的 Object 定义:

@JsonPropertyOrder({"quantity", "measure", "ingredient"})
public class Ingredient {
    public double quantity;
    public String measure;
    public int ingredient;
}

使用 Jackson CsvMapper的调用代码:

List<Ingredient> result = new CsvMapper()
    .readerWithTypedSchemaFor(Ingredient.class)
    .readValues(csvFile)
    .readAll();

我不习惯Java,所以这段代码可能会有一些小错误。 如果你看到一个,请随意编辑。

从 C# 的角度来看,我将进行以下更改:

  1. .trim()调用移到一个地方。 在这里,我通过使用of()创建Stream然后调用map (假设 Java 8 或更新版本)将输入行拆分成多个parts之后执行此操作。
  2. 删除实例化quantitymeasurement的默认值的行。 因为我们不必修剪,所以我们可以使用三元运算符在同一行上声明和实例化变量。
  3. 不要检查parts[1]是否为空。 由于""是后备值,因此parts[1]是否也是""也没关系。 这也意味着您不需要中间measurement变量。
public static Ingredient parseString(String line)
        throws InvalidIngredientException {        
    String[] parts = Stream.of(line.split(";")).map(p => p.trim()).toArray();
    if (parts.length == 1) {
        throw new InvalidIngredientException(EXP_MSG);
    }
    double quantity = parts[0].isEmpty() ? 1 : Double.parseDouble(parts[0]);    
    return new Ingredient(quantity, parts[1], parts[2]);
}

如果parts.length == 0parts[0]无法解析为Double ,您也有可能抛出InvalidIngredientException以外的错误。 我不确定在声明你的方法可以抛出哪些异常时你应该有多严格,但这里有一个版本应该捕获任何异常并且只返回你声明的InvalidIngredientException

public static Ingredient parseString(String line)
        throws InvalidIngredientException {     
    try { 
        String[] parts = Stream.of(line.split(";")).map(p => p.trim()).toArray();
        double quantity = parts[0].isEmpty() ? 1 : Double.parseDouble(parts[0]); 
        return new Ingredient(quantity, parts[1], parts[2]);
    }
    catch (Exception e) {
        throw new InvalidIngredientException(EXP_MSG);
    }
}

您可以做一些小事情来使您的代码看起来更好并稍微提高性能。

  1. 将行拆分为“\s;\s”时更改正则表达式。 这样你就可以避免多次调用 trim()
  2. 使用else if...else语法。 这将使您的代码不仅更短,而且更易于阅读。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM