Java++:对List对象列表属性值的快速搜索
思路:
1、传入数据源List,并指定要搜索的字段;将这些字段的值拼接成一个字符串,并保存每个对象的值的起始和结束位置:
2、搜索时,先使用正则表达式在保存的搜索字符串找到位置,再利用这些位置在索引数据数组中找到对应对象索引;
import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; public class FSearchTool { private StringBuffer mKeyWordString = new StringBuffer(); private List<Object> mSearchObjs = new ArrayList<>(); private int[] mIndexes; public FSearchTool(List<? extends Object> objects, String... fields) throws Exception { super(); init(objects, fields); } private void init(List<? extends Object> objs, String... fields) throws Exception { if (objs != null) { mKeyWordString.setLength(0); mSearchObjs.clear(); mSearchObjs = new ArrayList<>(objs); mIndexes = new int[mSearchObjs.size() * 2]; int index = 0; for (int i = 0; i < mSearchObjs.size(); i++) { Object info = mSearchObjs.get(i); // 指定要搜索的字段 String searchKey = getSearchKey(info, fields); // 将该字符串在总字符串中的起终位置保存下来,位置是索引值而非长度 int length = mKeyWordString.length(); mIndexes[index] = length; mKeyWordString.append(searchKey); length = mKeyWordString.length(); index++; // 保存新加搜索字段的索引值 mIndexes[index] = (length > 0) ? length - 1 : 0; index++; } } } /** * 通过反射从对象中取出指定字段的值 */ private String getSearchKey(Object obj, String... fields) throws Exception { StringBuilder searchKeys = new StringBuilder(); Class<? extends Object> clazz = obj.getClass(); try { for (String str : fields) { // 搜索字段使用空格隔开 Field f = clazz.getDeclaredField(str); f.setAccessible(true); Object val = f.get(obj); searchKeys.append(val).append(" "); f.setAccessible(false); } } catch (Exception e) { throw new Exception("取值异常:" + e.getMessage()); } return searchKeys.toString(); } /** * 搜索结果 * * @param keyWords * 搜索的关键字,要去掉首尾的空格 * @return 返回搜索到的对象 */ public List<Object> searchTasks(String keyWords) { List<Object> searchedTask = new ArrayList<>(); int[] searchIndex = getSearchIndex(keyWords); for (int index : searchIndex) { if (index != -1 && index < mSearchObjs.size() * 2) { Object info = mSearchObjs.get(index / 2); if (info != null && !searchedTask.contains(info)) { searchedTask.add(info); } } } return searchedTask; } /** * 找到匹配的索引数据 * * @param keyWords * 搜索的关键字 * @return 在初始化的索引数组的下标数组 */ private int[] getSearchIndex(String keyWords) { Pattern pattern = Pattern.compile(keyWords, Pattern.CASE_INSENSITIVE | Pattern.LITERAL); Matcher matcher = pattern.matcher(mKeyWordString.toString()); ArrayList<Integer> searchResult = new ArrayList<>(); while (matcher.find()) { // 不宜在此处再做循环,否则可能造成循环次数过多错误 searchResult.add(matcher.start()); } int[] searchIndexes = new int[searchResult.size()]; for (int i = 0; i < searchIndexes.length; i++) { int findIndex = findIndex(searchResult.get(i)); searchIndexes[i] = (findIndex / 2) * 2; } return searchIndexes; } /** * 使用二分法找到指定字符位置在索引数组中的位置 * * @param charAt * 字符在整个字符串中的位置 * @return 在索引数组中的位置 */ private int findIndex(int charAt) { int low = 0; int high = mIndexes.length - 1; int mid = -1; while (low <= high) { mid = (low + high) >>> 1; int midVal = mIndexes[mid]; if (midVal < charAt) { low = mid + 1; } else if (midVal > charAt) { high = mid - 1; } else { return mid; } } return mid; } }
代码示例:
public static void main(String[] args) { List<Student> students = new ArrayList<>(); students.add(new Student("001", "小王", "天府大道一街")); students.add(new Student("002", "小王", "天府大道二街")); students.add(new Student("003", "小红", "天府大道三街")); students.add(new Student("004", "小明", "天府大道四街")); students.add(new Student("005", "小王", "天府大道五街")); students.add(new Student("006", "小王", "软件园南门")); students.add(new Student("007", "小张", "吉泰路")); try { FSearchTool tool = new FSearchTool(students, "name", "address"); System.out.println(tool.searchTasks("明")); } catch (Exception e) { e.printStackTrace(); } }
输出结果:
[Student [id=004, name=小明, address=天府大道四街]]
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
2019-08-28 coding++:快速构建 kindeditor 富文本编辑器(一)
2019-08-28 coding++:解决Not allowed to load local resource错误-SpringBoot配置虚拟路径