【问题标题】:Is there any better way to find any string from multiple string array有没有更好的方法从多个字符串数组中找到任何字符串
【发布时间】:2018-10-24 08:13:07
【问题描述】:

在下面的示例中,有一些预定义的字符串数组,我在下面的示例中提到过,现在我的要求是如果每个数组中存在 boName,我需要调用为特定自定义字段定义的方法。有没有其他方法可以避免多个 for 循环。

public class MyClass {

    private static final String[] OTHER_CUSTOM_FIELD_RELATED_BO_NAME = { "A", "B", "C", "D", "E", "F", "G", "H" };
    private static final String[] TRANSACTION_CUSTOM_FIELD_RELATED_BO_NAME = { "A", "AB", "CD", "DE", "EG" };
    private static final String[] CRM_CUSTOM_FIELD_RELATED_BO_NAME = { "I", "J", "K", "L", "M" };
    private static final String[] ITEM_CUSTOM_FIELD_RELATED_BO_NAME = { "N", "O", "P", "Q" };
    private static final String[] ENTITY_CUSTOM_FIELD_RELATED_BO_NAME = { "AN", "ZY", "X", "P" };

    public static List<String> BusinessObjectDescribe(String boName) {
        List<String> fields = new ArrayList<String>();
        if (boName != null && !boName.isEmpty()) {
            for (String string : OTHER_CUSTOM_FIELD_RELATED_BO_NAME) {
                if (boName.equals(string)) {
                    fields.addAll(getOtherCustomFields());
                    break;
                }
            }

            for (String string : TRANSACTION_CUSTOM_FIELD_RELATED_BO_NAME) {
                if (boName.equals(string)) {
                    fields.addAll(getTransactionCustomFields());
                    break;
                }
            }

            for (String string : CRM_CUSTOM_FIELD_RELATED_BO_NAME) {
                if (boName.equals(string)) {
                    fields.addAll(getCRMCustomFields());
                    break;
                }
            }

            for (String string : ITEM_CUSTOM_FIELD_RELATED_BO_NAME) {
                if (boName.equals(string)) {
                    fields.addAll(getITEMCustomFields());
                    break;
                }
            }

            for (String string : ENTITY_CUSTOM_FIELD_RELATED_BO_NAME) {
                if (boName.equals(string)) {
                    fields.addAll(getEntityCustomFields());
                    break;
                }
            }

        }

        return fields;

    }

}

【问题讨论】:

  • 有很多方法可以进行高效的字符串搜索

标签: java string arraylist


【解决方案1】:

如果您使用的是 Java8,则可以利用函数式接口的优势。只需创建一个新函数,它将您的数组作为第一个参数,并将供应商函数作为第二个参数。在供应商中,您可以传递有关添加的逻辑。而且您需要多次调用该函数而不是重复代码。

【讨论】:

    【解决方案2】:

    要搜索,可以在 java-8 中使用以下内容:

    Arrays.stream(OTHER_CUSTOM_FIELD_RELATED_BO_NAME)
        .filter(e -> e.contains("A"))
        .findFirst();
    

    这里我们将数组转换为流,然后应用过滤器。如果找到匹配项,它将返回元素,否则将返回null。此外,.findFirst() 将在找到匹配项后立即停止搜索流。

    您可以使用相同的语法并根据需要搜索其他数组。

    【讨论】:

    • 最好解释一下这段代码的作用。 OP 可能不熟悉 Java 8 的特性。
    • 同意并编辑。 (实际上是在您发表评论之前对其进行编辑:-)
    • 然后你可以使用map来收集结果,并将id传递给addAll: fields.addAll( Arrays.stream(OTHER_CUSTOM_FIELD_RELATED_BO_NAME) .filter(e -> e.contains("A")) .findFirst() .map(s -> getOtherCustomFields()).orElse(Collections.EMPTY_LIST)) ;
    【解决方案3】:

    我会创建一个类来封装您在循环中执行的行为。

    class MyClass {
        class BoNameHandler {
            private Collection<String> applicableNames;
            private Supplier<Collection<String>> getter;
            BoNameHandler(String[] names, Supplier<Collection<String>> g) {
                applicableNames = Arrays.asList(names);
                getter = g;
            }
            void addIfApplicable(String boName, List<String> addTo) {
                if (applicableNames.stream().filter(boName::equals).findFirst().isPresent()) {
                    addTo.addAll(getter.get());
                }
            }
        }
        List<BoNameHandler> handlers = new ArrayList<>();
        MyClass() {
            handlers.add(new BoNameHandler(OTHER_CUSTOM_FIELD_RELATED_BO_NAME, this::getOtherCustomFields));
            handlers.add(new BoNameHandler(TRANSACTION_CUSTOM_FIELD_RELATED_BO_NAME, this::getTransactionCustomFields));
            // and the others
        }
    }
    

    这会将您的代码减少到

    public static List<String> BusinessObjectDescribe(String boName) {
        List<String> fields = new ArrayList<String>();
        for (BoNameHandler handler : handlers) {
            handler.addIfApplicable(boName, fields);
        }
        return fields;
    }
    

    我不知道您的方法是什么样的,但如果它们与 BO_NAME 一样固定,您不妨将它们放在一个 enum 中。

    【讨论】:

    • 感谢您的回复,能否请您解释一下有关 Supplier> getter 的信息?这是来自 jjava.util.function.Supplier 吗??
    • @AmrendraKumar 是的,那是java.util.function.Supplier。这意味着它是一个不带参数并返回 Strings 集合的方法(就像您的 getXXX() 方法似乎所做的那样)。
    • 这个 handlers.add(new BoNameHandler(OTHER_CUSTOM_FIELD_RELATED_BO_NAME, this::getOtherCustomFields));是不是需要把构造函数的第二个参数改成Object???
    • @AmrendraKumar 这取决于你得到的错误。您可能需要将 getter 成员和构造函数更改为 BoNameHandler(String[] names, Supplier&lt;List&lt;String&gt;&gt; g)
    • 感谢您的回复,如果理解您的代码,所有方法都只会被预先调用,但我的要求是,如果 boName 匹配,那么只有我会调用方法,因为在每个方法中都有基于匹配的 REST api 调用。
    【解决方案4】:

    作为Set,数学集合{ a, b, c },其实是最符合逻辑的数据结构,用那个吧。

    private static final Set<String> OTHER_CUSTOM_FIELD_RELATED_BO_NAME =
        Set.of( "A", "B", "C", "D", "E", "F", "G", "H" );
    private static final Set<String> TRANSACTION_CUSTOM_FIELD_RELATED_BO_NAME =
        Set.of( "A", "AB", "CD", "DE", "EG" );
    private static final Set<String> CRM_CUSTOM_FIELD_RELATED_BO_NAME =
        Set.of( "I", "J", "K", "L", "M" );
    private static final Set<String> ITEM_CUSTOM_FIELD_RELATED_BO_NAME =
        Set.of( "N", "O", "P", "Q" );
    private static final Set<String> ENTITY_CUSTOM_FIELD_RELATED_BO_NAME =
        Set.of( "AN", "ZY", "X", "P" );
    
    
    public static List<String> BusinessObjectDescribe(String boName) {
        List<String> fields = new ArrayList<>();
        if (boName != null && !boName.isEmpty()) {
            if (OTHER_CUSTOM_FIELD_RELATED_BO_NAME.contains(boName)) {
                fields.addAll(getOtherCustomFields());
            }
            if (TRANSACTION_CUSTOM_FIELD_RELATED_BO_NAME.contains(boName)) {
                fields.addAll(getTransactionCustomFields());
            }
            if (CRM_CUSTOM_FIELD_RELATED_BO_NAME.contains(boName)) {
                fields.addAll(getCRMCustomFields());
            }
            if (ITEM_CUSTOM_FIELD_RELATED_BO_NAME.contains(boName)) {
                fields.addAll(getITEMCustomFields());
            }
            if (ENTITY_CUSTOM_FIELD_RELATED_BO_NAME.contains(boName)) {
                fields.addAll(getEntityCustomFields());
            }
        }
        return fields;
    }
    

    如果你的java版本还是不知道Set.of(java 9之前)

    private static final Set<String> OTHER_CUSTOM_FIELD_RELATED_BO_NAME = new HashSet<>();
    static {
        Collections.addAll(OTHER_CUSTOM_FIELD_RELATED_BO_NAME,
            "A", "B", "C", "D", "E", "F", "G", "H" );
    }
    

    Set 是最快的数据结构。那么为什么做到最好。

    【讨论】:

    • 将有助于指出这将适用于 java 9+
    • @NicholasK 下面添加了一个 pre-9 解决方案:“如果您的 java 版本仍然...”,但谢谢;我会添加版本号。
    【解决方案5】:

    我还会考虑将所有这些数组放到一个 Map 或 Map 中,然后再进行处理。

    【讨论】:

      猜你喜欢
      • 2011-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-25
      • 1970-01-01
      • 1970-01-01
      • 2015-08-07
      • 2016-04-29
      相关资源
      最近更新 更多