我们正在尝试搜索一个类及其所有字段以查找特定的搜索字符串。 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 无法以符合应用程序域业务规则的方式自动搜索对象的内容。
理解域数据是你的工作,而不是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 确实支持反射编程。您可以在运行时查询类的结构,以查看其字段。
但这很复杂,而且很难做到正确。稍后对代码的更改可能会破坏您的反射代码。一般来说,使用反射是最后的解决方案。