用多个参数搜索,java集合选择建议

时间:2012-08-09 10:43:47

标签: java android collections generic-collections

在下面描述的情况下,我应该使用什么数据结构:

我有一个简单的bean:

 public class Points { 

    private String name; 
    private String address; 
    private int phone; 
    private int coord1; 
    private int coord2; 

    //getters+setters 

    }

我想创建几个bean并将它们存储在某种数据结构中。 并且能够使用两个参数进行搜索 - 名称和地址。

例如,用户输入“7” - 它给了他几个对象, 哪个名称或地址包含此字符?

我应该使用什么数据结构以及如何搜索它?

如果它很重要,我实际上需要这个实现到我的Android应用程序 - 我想在地图上搜索我的观点 此外,我不想创建一个数据库到目前为止,因为它们只有20个。

非常感谢你。

2 个答案:

答案 0 :(得分:1)

trie 似乎很合适。找到具有特定前缀的所有字符串是一种高效的数据结构。

如果您想使用现有的Java集合之一,可以使用TreeSet及其floor()方法在所需前缀之前获取元素 - 然后开始迭代集合它仍然匹配。

如果您正在寻找子字符串搜索,而不仅仅是前缀 - 您可能希望使用 suffix tree
使用java现有容器的(低效)替代方法是将密钥的所有子字符串存储在SetMap中,但它需要四倍的空间。

答案 1 :(得分:1)

尝试java的集合,例如HashMap中。虽然我在PC上运行了这个,但搜索了10000个项目 返回3440结果,花了76ms。

    class Points {

        String name;
        String address;
        int phone;
        int coord1;
        int coord2;

        // getters+setters
    };

    class PointsIdentifier {

        private String name;
        private String address;

        public PointsIdentifier(String name, String address) {
            this.name = name;
            this.address = address;

        }

        public boolean contains(String seq) {
            return name.contains(seq) || address.contains(seq);
        }

        @Override
        public boolean equals(Object obj) {
            Points other = (Points) obj;
            return name.equals(other.name) && address.equals(other.address);
        }

        @Override
        public int hashCode() {
            return name.hashCode() + address.hashCode();
        }
    };

    class PointsCollection {
        private Map<PointsIdentifier, Points> map;

        public PointsCollection() {
            map = new HashMap<PointsIdentifier, Points>();
        }

        public void add(Points p) {
            map.put(new PointsIdentifier(p.name, p.address), p);
        }

        public List<Points> findIdsContaining(String seq) {
            List<Points> resultList = new ArrayList<Points>();
            for (Entry<PointsIdentifier, Points> entry : map.entrySet()) {
                if (entry.getKey().contains(seq)) {
                    resultList.add(entry.getValue());
                }
            }
            // optionally cache result
            return resultList;
        }
    }

    public class Question_11881630 {

        public static void main(String[] args) {
            PointsCollection places = createCollection(10000);
            System.out.println("Collection created");
        String seq = "1";

        System.out.format("Searching for: \"%s\"\n", seq);
        List<Points> verifySearch = verifySearch(places, seq);
        //show(verifySearch);
    }

    private static void show(List<Points> verifySearch) {
        int i = 1;
        for (Points p : verifySearch) {
            System.out.println(i + ": " + p.name + ", " + p.address);
            i++;
        }
    }

    private static List<Points> verifySearch(PointsCollection places, String seq) {
        long start = System.currentTimeMillis();
        List<Points> searchResult = places.findIdsContaining(seq);
        System.out.println("Search results: " + searchResult.size());
        long end = System.currentTimeMillis();
        System.out.println("Operation time: " + formatTime(end - start));
        return searchResult;
    }

    private static String formatTime(long elapsed) {
        return elapsed + " miliseconds";
    }

    private static PointsCollection createCollection(int number) {
        PointsCollection coll = new PointsCollection();
        while (number > 0) {
            coll.add(createSamplePoint(number));
            number--;
        }
        return coll;
    }

    private static Points createSamplePoint(int number) {
        Points p = new Points();
        p.name = "VeryVeryLongName: " + number;
        p.address = "VeryVeryLongLongAddress: " + number;
            p.coord1 = 123;
            p.coord2 = 456;
            return p;
        }
    }