2011-11-13 100 views
0

想象一下,我有一组复杂的对象,假设他们有名字,姓氏和颜色。按属性或类型从一组对象中选择对象

我想检索该组中所有对象都是红色的选择,并且姓氏以“K”开头。

确实java包含一个数据结构,我可以存储这些对象,允许这种选择?有没有一个优雅的解决方案,不涉及编写一堆for循环?

我想这样做,而不使用任何Java数据库库。

+0

可以实现它youself。一些自定义集合也会根据所需的属性存储索引。在添加对象时,会扫描属性值并将索引存储在索引集合中。每个索引集合可以实现为'Map >',其中键是属性值并且集合 - 是共享相同属性值的对象的集合。 –

回答

0

AFAIK,没有Java中的数据结构,它可以让你从盒子里完成这些操作。你会需要像inverted index这样的工作。 Lucene允许您执行所有您刚才非常有效地说的搜索操作。我相信它也有一个In-Memory存储,所以它应该就够了。

0

这里是一个样本,就在我的头顶(我并没有实现remove方法):

import java.lang.reflect.Field; 
import java.util.ArrayList; 
import java.util.HashMap; 
import java.util.HashSet; 
import java.util.List; 
import java.util.Map; 
import java.util.Map.Entry; 
import java.util.Set; 

public class IndexedCollection<E> extends ArrayList<E> { 
    private Map<String, Map<Object, Set<E>>> indices = new HashMap<String, Map<Object, Set<E>>>(); 

    public IndexedCollection(String...indices) { 
     for (String index: indices) { 
      this.indices.put(index, new HashMap<Object, Set<E>>()); 
     } 
    } 

    public boolean add(E entry) { 
     try { 
       Map<String, Object> objectIndices = collectIndices(entry); 

       for (Entry<String, Object> objectIndex: objectIndices.entrySet()) { 
        Map<Object, Set<E>> map = this.indices.get(objectIndex.getKey()); 
        Set<E> set = map.get(objectIndex.getValue()); 

        if (set == null) { 
         set = new HashSet<E>(); 
         map.put(objectIndex.getValue(), set); 
        } 

        set.add(entry); 
       } 

       return super.add(entry); 
     } 
     catch (Exception e) 
     { 
      throw new RuntimeException("Failed to collect object indices", e); 
     } 
    }; 

    public Set<E> findByIndex(String name, Object value) { 
     Map<Object, Set<E>> index = this.indices.get(name); 

     if (index != null) 
      return index.get(value); 

     return null; 
    } 

    public Set<E> findByIndices(Index...indices) { 
     Set<E> results = null; 

     for (Index index: indices) { 
      Set<E> tmp = findByIndex(index.name, index.value); 

      if (tmp.size() == 0) 
       return null; 

      if (results == null) 
       results = tmp; 
      else { 
       Set<E> newResult = new HashSet<E>(); 
       for (E value: results) { 
        if (tmp.contains(value)) 
         newResult.add(value); 
       } 

       results = newResult; 
} 
     } 

     return results; 
    } 

    private Map<String, Object> collectIndices(E e) throws IllegalArgumentException, IllegalAccessException { 
     Map<String, Object> indices = new HashMap<String, Object>(); 

     Field[] fields = e.getClass().getDeclaredFields(); 

     for (Field field: fields) { 
      if (this.indices.containsKey(field.getName())) { 
       boolean accessible = field.isAccessible(); 
       field.setAccessible(true); 
       indices.put(field.getName(), field.get(e)); 
       field.setAccessible(accessible); 
      } 
     } 

     return indices; 
    } 

    public static class Index { 
     private String name; 
     private Object value; 

     public Index(String name, Object value) { 
      this.name = name; 
      this.value = value; 
     } 
    } 
}