使用列表和映射在类中搜索字符串值

问题描述 投票:0回答:1

我们正在尝试搜索一个类及其所有字段以查找特定的搜索字符串。 Java 是否包含用于搜索类中值的本机库?否则,我在下面写了一个基本方法。

public class Account {
    private String accountId;
    private Set<String> contactIds = new HashSet<>();
    private Map<String, String> phones = new HashMap<>();
    private Map<String, String> emails = new HashMap<>();
    private Set<String> titles = new HashSet<>();
}

尝试:

private boolean hasSearchString(Account account, String seachString) {
    for (String item: account.getContactNames()) {
         if (item.contains(searchString))
            return true;
    }
    for (String item: account.getPhones().keySet()) {
        if (item.contains(searchString))
           return true;
    }
    for (String title: account.getEmails().keySet()) {
        if (item.contains(searchString))
           return true;
    }
    ....
}
java
1个回答
0
投票

tl;博士

不。 Java 无法以符合应用程序域业务规则的方式自动搜索对象的内容。

理解域数据是你的工作,而不是Java的。

提示:了解通常用于封装对数据存储(例如数据库)的访问的Repository模式。

条款

更正一些术语...

搜索一个类及其所有字段

类是运行时创建对象的模板。就像饼干模压出饼干一样。

所以你想搜索对象字段中的内容,而不是类。

Java 库包含用于搜索值的本机库

术语 native 表示非 Java 代码,用 C 或 Rust 或 Swift 等编写的代码,提前编译为机器语言。

相比之下,Java 被编译为字节码。随后,在运行时,字节码解释或编译为机器语言。

面向对象设计

您的示例数据结构不是面向对象的。

显然您的意思是用

Account
来代表一组联系人,其中联系人是具有 ID、姓名、电话号码、电子邮件地址和头衔的人。

因此,创建一个自定义类来代表您的每个实体:帐户和联系人。

如果自定义类的主要目的是透明地通信浅层不可变数据,则将该类定义为记录

package work.basil.example.searching;

import java.util.UUID;

public record Contact( UUID id , String name , String title , String email , String phone ) { }
package work.basil.example.searching;

import java.util.Collection;

public record Account( String name , Collection < Contact > contacts ) { }

Repository

要管理对数据存储的访问,请创建一个专用于该目的的类。通常称为

Repository
。 在我们的
Repository
实现中,我们为此演示创建了一些假数据。

package work.basil.example.searching;

import java.util.Collection;
import java.util.List;
import java.util.UUID;

public class Repository
{
    // Fields.
    private final Collection < Account > accounts;

    // Constructors
    public Repository ( )
    {
        this.accounts = this.fetchAccounts ( );
    }

    public Account fetchAccountByName ( final String aName )
    {
        for ( Account account : this.accounts )
        {
            if ( account.name ( ).equalsIgnoreCase ( aName ) ) { return account; }
        }
        return null;
    }

    // Helpers
    private List < Account > fetchAccounts ( )
    {
        return
                List.of (
                        new Account (
                                "West" ,
                                List.of (
                                        new Contact ( UUID.fromString ( "0fc8ebc7-e8ef-4a5f-8788-b8d2a18b470a" ) , "Alice" , "Boss" , "[email protected]" , "555-1234" ) ,
                                        new Contact ( UUID.fromString ( "14f9e482-8e59-4e75-8955-5b3bc13e52ff" ) , "Bob" , "Secretary" , "[email protected]" , "555-4321" ) ,
                                        new Contact ( UUID.fromString ( "db0a0a51-cd88-4d2e-8cf7-45535f1cf09b" ) , "Carol" , "Engineer" , "[email protected]" , "555-2345" )
                                )
                        ) ,
                        new Account (
                                "East" ,
                                List.of (
                                        new Contact ( UUID.fromString ( "013da36d-cc0f-4c07-b9ab-077cbf152025" ) , "Davis" , "Boss" , "[email protected]" , "555-7890" ) ,
                                        new Contact ( UUID.fromString ( "9f4282aa-1ea5-4c3f-888c-abe68135c489" ) , "Edna" , "Secretary" , "[email protected]" , "555-0987" ) ,
                                        new Contact ( UUID.fromString ( "184ca072-b945-48bb-ba9f-4423df857837" ) , "Frank" , "Engineer" , "[email protected]" , "555-8907" )
                                )
                        )
                );
    }
}

搜索中

注意我们如何有一个方法

fetchAccountByName
根据我们的虚假数据按名称“West”或“East”返回特定帐户。

使用示例:

Repository repository = new Repository ( );
Account eastAccount = repository.fetchAccountByName ( "East" );
System.out.println ( "eastAccount.toString() = " + eastAccount );

eastAccount.toString() = 帐户[名称=East,联系人=[联系人[id=013da36d-cc0f-4c07-b9ab-077cbf152025],名称=戴维斯,职位=老板,[电子邮件受保护],电话=555-7890 ],联系人[id=9f4282aa-1ea5-4c3f-888c-abe68135c489,姓名=Edna,职位=秘书,[电子邮件受保护],电话=555-0987],联系人[id=184ca072-b945-48bb-ba9f- 4423df857837,姓名=弗兰克,职位=工程师,[电子邮件受保护],电话=555-8907]]]

显然您想要搜索一个或多个联系人具有特定名称的帐户。因此,让我们向

Repository
类添加另一个方法。

public Collection < Contact > fetchContactByPersonName ( final String aContactName )
{
    ArrayList < Contact > foundContacts = new ArrayList <> ( );
    for ( Account account : this.accounts )
    {
        for ( Contact contact : account.contacts ( ) )
        {
            if ( contact.name ( ).equalsIgnoreCase ( aContactName ) )
            {
                foundContacts.add ( contact );
            }
        }
    }
    return List.copyOf ( foundContacts );  // Generally best to return an unmodifiable list.
}

搜索名为 Frank 的联系人。

Collection < Contact > contactsNamedFrank = repository.fetchContactByPersonName ( "Frank" );
System.out.println ( "contactsNamedFrank.toString() = " + contactsNamedFrank );

contactsNamedFrank.toString() = [联系人[id=184ca072-b945-48bb-ba9f-4423df857837, name=Frank, title=Engineer, [电子邮件受保护], 电话=555-8907]]

搜索不存在的名称。我们预计会有一个空集合。

Collection < Contact > contactsNamedZappa = repository.fetchContactByPersonName ( "Zappa" );
System.out.println ( "contactsNamedZappa.toString() = " + contactsNamedZappa );

contactsNamedZappa.toString() = []

反思

Java 确实支持反射编程。您可以在运行时查询类的结构,以查看其字段。

但这很复杂,而且很难做到正确。稍后对代码的更改可能会破坏您的反射代码。一般来说,使用反射是最后的解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.