1. 程式人生 > >模糊查詢記憶體查詢java實現

模糊查詢記憶體查詢java實現

  下面說說看到的工作專案中的程式碼,是這個樣子的,事先查詢一次資料庫,將查詢到的整張表的資料存到記憶體,以後使用時不再查詢資料庫,而直接操作記憶體中的資料,這主要用於資料庫中的資料比較穩定,不會輕易改變的情況,比如法律條款,醫療術語,拿到這些資料主要是用於模糊查詢,我對相關程式碼進行了改動,把原來固定的通過某些欄位的模糊查詢改為可選擇通過哪些欄位進行模糊查詢,下面看一下程式碼

 

  控制層,服務層沒什麼可說的,直接看程式碼

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介面,是用來確定查詢範圍與結果範圍的。

  好了,就說到這裡吧,有喜歡的評論一下吧。