通知 网站从因情语写改为晴雨,这个网站的模板也从calmlog_ex改为 whimurmur

模糊查询内存查询java实现

5239人浏览 / 0人评论 / | 作者:因情语写  | 分类: JAVA基础  | 标签: JAVA

作者:因情语写

链接:https://www.qingyu.blue/article/287

声明:请尊重原作者的劳动,如需转载请注明出处


    下面说说看到的工作项目中的代码,是这个样子的,事先查询一次数据库,将查询到的整张表的数据存到内存,以后使用时不再查询数据库,而直接操作内存中的数据,这主要用于数据库中的数据比较稳定,不会轻易改变的情况,比如法律条款,医疗术语,拿到这些数据主要是用于模糊查询,我对相关代码进行了改动,把原来固定的通过某些字段的模糊查询改为可选择通过哪些字段进行模糊查询,下面看一下代码

  控制层,服务层没什么可说的,直接看代码

package study.fuzzysearch.controller;

import java.util.List;

import study.fuzzysearch.bean.User;
import study.fuzzysearch.service.UserService;

public class UserController {
    public List<User> getUserByFuzzySearch(String searchStr, String[] searchFields, boolean startMatch)
    {
        return new UserService().getUserByFuzzySearch(searchStr, searchFields, startMatch);
    }
}
package study.fuzzysearch.service;

import java.util.List;

import study.fuzzysearch.bean.User;
import study.fuzzysearch.dao.UserDao;

public class UserService {
    public List<User> getUserByFuzzySearch(String searchStr, String[] searchFields, boolean startMatch)
    {
        return new UserDao().getUserByFuzzySearch(searchStr, searchFields, startMatch);
    }
}

    DAO层实现如下

package study.fuzzysearch.dao;

import java.util.List;

import study.fuzzysearch.bean.User;
import study.fuzzysearch.interf.Filter;
import study.fuzzysearch.interf.impl.FuzzyImpl;

public class UserDao {
    // 模拟从数据库取数据
    User[] users = new User[]{
        new User("10001", "zihan", "zh"),
        new User("zh002", "zuosan", "zs"),
        new User("10003", "zisha", "zs"),
        new User("10004", "zizhai", "zw"),
        new User("10005", "zaohu", "zh"),
        new User("10006", "zhanghu", "zh")
    };
    public List<User> getUserByFuzzySearch(String searchStr, String[] searchFields, boolean startMatch)
    {
        // 可以初始化一次保存起来,留以后用
        FuzzyImpl<User> fuzzy = new FuzzyImpl<User>(users) {
            public String getName(User t) {
                return t.getUserName();
            }
            
            public String getPy(User t) {
                return t.getPy();
            }
            
            public String getUserId(User t) {
                return t.getUserId();
            }
        };
        
        final String[] finalSearchFields = searchFields;
        return fuzzy.search(searchStr, new Filter<User>() {
            
            public String[] searchFields() {
                return finalSearchFields;
            }
            
            // 这里可以定制一些情况,比如张三在黑名单里,不返回张三
            public boolean match(User t) {
                if(t.getUserId().equals("10006"))
                    return false;
                
                return true;
            }
        }, startMatch);
    }
}

    再看下两个接口

package study.fuzzysearch.interf;

public interface Filter<T> {
    public boolean match(T t);
    public String[] searchFields();
}

    上面的接口的match可以过滤掉无效的结果,searchFields指定通过哪些字段进行模糊查询

package study.fuzzysearch.interf;

public interface Fuzzy<T> {
    
    String getName(T t);
    String getPy(T t);
    String getUserId(T t);
}

    上面的接口指定可以通过名字,拼音码,id进行模糊查询,如果有更多的选择,可以增加方法

  下面看一下最核心的方法FuzzyImpl类

package study.fuzzysearch.interf.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import study.fuzzysearch.interf.Filter;
import study.fuzzysearch.interf.Fuzzy;

public abstract class FuzzyImpl<T> implements Fuzzy<T>{
    private T[] datas;
    private Map<String, List<T>> nameMap = new HashMap<String, List<T>>();
    private Map<String, List<T>> pyMap = new HashMap<String, List<T>>();
    private Map<String, List<T>> userIdMap = new HashMap<String, List<T>>();
    private Map<String, Map<String, List<T>>> allMap = new HashMap<String, Map<String, List<T>>>();
    
    public FuzzyImpl(T[] datas)
    {
        this.datas = datas;
        
        List<T> temp = null;
        if(null != datas && datas.length > 0)
        {
            for(int i = 0; i < datas.length; i++)
            {
                temp = nameMap.get(getName(datas[i]));
                if(temp == null)
                {
                    temp = new ArrayList<T>();
                }
                
                temp.add(datas[i]);
                nameMap.put(getName(datas[i]), temp);
                
                temp = pyMap.get(getPy(datas[i]));
                if(temp == null)
                {
                    temp = new ArrayList<T>();
                }
                
                temp.add(datas[i]);
                pyMap.put(getPy(datas[i]), temp);
                
                temp = userIdMap.get(getUserId(datas[i]));
                if(temp == null)
                {
                    temp = new ArrayList<T>();
                }
                
                temp.add(datas[i]);
                userIdMap.put(getUserId(datas[i]), temp);
            }
            
            allMap.put("py", pyMap);
            allMap.put("userId", userIdMap);
            allMap.put("name", nameMap);
        }
    }
    
    public List<T> search(String searchStr, Filter<T> f, boolean startMatch)
    {
        List<T> result = new ArrayList<T>();
        List<T> temp = new ArrayList<T>();
        if(null != searchStr && searchStr.length() > 0)
        {
            String[] searchFields = f.searchFields();
            if(null != searchFields && searchFields.length > 0)
            {
                for(int i = 0; i < searchFields.length; i++)
                {
                    Map<String, List<T>> tempSearchMap = allMap.get(searchFields[i]);
                    temp.addAll(search(searchStr, tempSearchMap, startMatch));
                }

                Set<T> tempSet = new HashSet<T>(temp);
                temp = new ArrayList<T>(tempSet);
                
                for(int i = 0; i < temp.size(); i++)
                {
                    if(f.match(temp.get(i)))
                    {
                        result.add(temp.get(i));
                    }
                }
            }
        }
        
        return result;
    }
    
    public List<T> search(String searchStr, Map<String, List<T>> compMap, boolean startMatch)
    {
        List<T> result = new ArrayList<T>();
        Set<String> keys = compMap.keySet();
        Iterator<String> keyIte = keys.iterator();
        while(keyIte.hasNext())
        {
            String next = keyIte.next();
            if(startMatch)
            {
                if(next.startsWith(searchStr))
                {
                    result.addAll(compMap.get(next));
                }
            }
            else
            {
                if(next.contains(searchStr))
                {
                    result.addAll(compMap.get(next));
                }
            }
        }
        
        return result;
    }
    
    public T[] getAllDatas()
    {
        return datas;
    }
}

    构造器中将名字,拼音码,ID分别存在了Map中,而且相同的名字,拼音码,ID存在了一起,这样减小了查询时的次数,search方法根据searchFields从名字,拼音码或者ID的Map中查询结果,并将结果合并去重得到最终结果

  再看一下测试代码

package study.fuzzysearch.test;

import study.fuzzysearch.controller.UserController;

public class Test {
    public static void main(String[] args) 
    {
        // getUserByFuzzySearch
        UserController controller = new UserController();
        
        System.out.println(controller.getUserByFuzzySearch("zh", new String[]{"name", "userId", "py"}, true));
        System.out.println(controller.getUserByFuzzySearch("zh", new String[]{"name", "py"}, false));
    }
}

    结果如下

  可以对照着users的内容分析结果

  代码是jdk5.0下的,所以没有用到什么高级特性,其中值得说的地方就是Fuzzy接口中的方法,里面的方法实现是在新建FuzzyImpl对象的时候,因为这时会确定要进行模糊查询的对象是什么,从而得到对象的名字,拼音码,ID,这里算是个技巧了,在对象不同的情况下通过统一的方法获取想要的数据,至于Filter接口,是用来确定查询范围与结果范围的。

  好了,就说到这里吧,有喜欢的评论一下吧。


自己写的文章声明标题示例:


点赞(0) 打赏

全部评论

还没有评论!