2

我经常发现自己编写的代码可以从多个子列表中构建一个列表。作为一个简单的示例,假设您有一个需要验证为列表的列表。写这个(必须)的一种方法是:

import static com.google.common.collect.Lists.newArrayList;

import java.util.List;

public class Product {

    private String name;
    private int height;

    public static List<String> validateList(List<Product> products) {
        List<String> result = newArrayList();
        valideListSize(products, result);
        for (Product product : products) {
            product.validate(result);
        }
        return result;
    }

    private static void valideListSize(List<Product> products,
            List<String> result) {
        if (products.size() > 1000) {
            result.add("List too large");
        }
    }

    private void validate(List<String> result) {
        if (name.length() > 30) {
            result.add("Name contains too many characters");
        }
        if (height > 40) {
            result.add("Product too high");
        }
    }

}

但是,为了简单/维护/重用,我不喜欢将验证单个产品的逻辑与将验证结果列表添加到另一个现有列表中。我还认为改变参数会导致更难调试代码。所以我更喜欢功能性更强的风格。目前我通常会这样写(使用来自 Google Guava 的 newArrayList):

import static com.google.common.collect.Lists.newArrayList;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;

import java.util.List;

public class Product {

    private String name;
    private int height;

    public static List<String> validateList(List<Product> products) {
        List<String> result = newArrayList();
        result.addAll(valideListSize(products));
        for (Product product : products) {
            result.addAll(product.validate());
        }
        return result;
    }

    private static List<String> valideListSize(List<Product> products) {
        if (products.size() > 1000) {
            return singletonList("List too large");
        }
        return emptyList();
    }

    private List<String> validate() {
        List<String> result = newArrayList();
        if (name.length() > 30) {
            result.add("Name contains too many characters");
        }
        if (height > 40) {
            result.add("Product too high");
        }
        return result;
    }

}

这会创建许多寿命很短的小型数组列表,其中许多通常是空的(没有验证错误)。这种代码在实践中会效率低下还是在生产环境中使用这种风格可以吗?有没有更有效的方法(可能使用 Guava)来做我想做的事,同时仍然保持代码干净、易于阅读并符合 Java 最佳实践?

作为一名专业的 Java 开发人员,您会做什么?

编辑:请参阅我对第一条评论的回答,为什么我更喜欢第二种方式。我更喜欢代码的可维护性/可读性而不是过早的优化,但是因为我在日常编程中经常看到这种模式,所以我想知道是否有一种至少同样干净的简单方法。使用某种连接列表视图怎么样,例如 Iterables.concat?或者这是否也创建了许多中间类?

4

2 回答 2

0

回答我自己的问题:即使在单产品验证方法中创建许多新列表时,Java 在性能方面也做得很好。我定时验证 300000 个产品列表 10 次(预热后)。

传递一个 Arraylist 的第一个实现需要 275 毫秒。使用 LinkedList 需要 300 毫秒。可能创建中间 ArrayList 的第二个实现需要 760 毫秒。使用 LinkedList 需要 580 毫秒。使用 Guava 的 ImmutableList 构建器需要 1150 毫秒。

所以我想我会继续使用我的第二种方法(也许对不需要随机访问的小列表使用 LinkedList)。

于 2013-04-19T09:34:49.020 回答
0

您可以使用不相交集数据结构(也称为联合查找数据结构)有效地完成此操作。有几种在线可用的实现,例如这里

于 2013-04-11T15:47:13.323 回答