我有1个需求,是实现1个id,对应多个对象。用map的话,第二次put同一个id的时候会把之前的value覆盖,这个大家都知道。
然后需要通过id,查找他对应的所有对象。看看大家有什么好想法,我实现了但是我感觉占地内存不少。。如果数据量大,内存吃紧。谢谢大家了就搞个 100 分吧。呵呵

解决方案 »

  1.   

    我也用这个,可是你有没有想过,arraylist如果申请 1000,10000个会是多大的内存消耗,而且你可能用到的某1个arraylist 也只是几个,都浪费了大虾
      

  2.   

    一般情况下就这个够了,如果预先知道对象的个数的话使用List也不会浪费空间。如果真的在这个地方是性能瓶颈,那只能根据特殊情况采取特殊的处理,那是case by case的事情。
      

  3.   

    HashMap<String,String> KeyMap=new HashMap<String,String>();
    HashMap<String,String> etyMap=new HashMap<String,String>();
    添加对象的时候
    String sGuid=getGuid();
    etyMap.push(sGuid,obj);ids=(keyMap.get(id)!=null?keyMap.get(id):"")+sGuid;
    keyMap.put(id,ids);
      

  4.   

    晕,id之间应该有个分隔符的
    ids=(keyMap.get(id)!=null?keyMap.get(id):"")+"|"+sGuid;
      

  5.   

    HashMap<String, ArrayList<yourObject>> map;
    ...
    map.get(key).add(value);//添加
    ...
    map.get(key)//返回对应的LIST
    ...
      

  6.   


    楼上的你写的什么啊。。
    etyMap.push(sGuid,obj);
    这个是新方法吗?
      

  7.   


    都说过这个方法极大的浪费arraylist了而且可能要申请 n多 arraylist
      

  8.   

    写错了,push是stack的方法,应该是put,刚刚还在写堆栈操作程序,有点乱了
      

  9.   

    public class OBJ {
        protected ArrayList<YourObj> list;
        public OBJ() {
            list = new ArrayList<YourObj>();
        }    public ArrayList<YourObj> getItems(String key) {
            ArrayList<YourObj> reList = new ArrayList<YourObj>();
            for(int i = 0; i < list.size(); i++) {
                YourObj obj = list.get(i);            if(obj.getId().equals(key)) {
                    reList.add(obj);
                }
            }
        }    public void add(YourObj obj) {
            ....
        }
    }参考着干吧,效率太低了,我都不好意思!
      

  10.   

    我新手,想了一下也就会这个HashMap <String,ArrayList>,期待大虾们的回答。
      

  11.   

    HashMap<String,HashSet<myClass>>也可以。
      

  12.   

    还有一种方法,ID设为String型HashMap<String, Integer> keyLenList;
    HashMap<String, YourObj> valueList;//这个结构类似:"key_1"、"key_2"get(key) {
        ArrayList reList...
        for(int i = 0; i < keyLenList.get(key); i++) {
            StringBuffer strKey = key.append("_").append(i);
            reList.add(valueLis.get(strKey));
        }    return reList;
    }
    ...就写这么多了...
      

  13.   

    我想到点东西。。
    LZ的问题是不是跟输入法类似
    比如:我输入Sh的时候,表示的意思可能是“时候”,也可以是“上海”。
    如果输入的是kj的话,表示的意思可以是“烤鸡”,可以是“空间”,可以是“科技”,也可以是“看见”
    想到就这么多了
      

  14.   

    import java.util.*;
    class MyClass implements Comparable<MyClass>{
    String name;
    //other....
    MyClass(String name){
    this.name=name;
    }
    //geters ....
    //seters.....
    public int compareTo(MyClass mc){
    return name.compareTo(mc.name); //
    }
    public boolean equals(MyClass mc){
    if(name.equals(mc.name)){
    return true;
    }
    return false;
    }
    public String toString(){
    return name;
    }
    }public class MyCollection{
    private HashMap<String,TreeSet<MyClass>> myMap=new HashMap<String,TreeSet<MyClass>>();
    public void put(String id,MyClass mc){
    TreeSet<MyClass> tree=myMap.get(id);
    if(tree==null){
    TreeSet<MyClass> treeA=new TreeSet<MyClass>();
    treeA.add(mc);
    myMap.put(id,treeA);
    }else{
    tree.add(mc);
    }
    }
    public TreeSet<MyClass> get(String id){
    return myMap.get(id);
    }
    public void printAll(String id){
    TreeSet<MyClass> tree=myMap.get(id);
    for(MyClass mc:tree){
    System.out.println(mc);
    }
    }
    public static void main(String[] args){
    MyCollection myCollection=new MyCollection();
    myCollection.put("1",new MyClass("one"));
    myCollection.put("2",new MyClass("two"));
    myCollection.put("1",new MyClass("oneone"));
    myCollection.put("1",new MyClass("one"));
    myCollection.put("2",new MyClass("twotwo"));
    myCollection.printAll("1");
    }}
    //之所以MyClass 实现了Comparable以及用了TreeSet,是为了查找一个对象方便,可以遍历整个myMap来查。但这个问题和你的要求没有关系。
    //用TreeSet还有一意思是相同的对象就没有必要再放进去了。
      

  15.   

    我在想能不能改变对象的构造,比如往对象中封装一个id变量,存储的是这些对象对应的id,然后将所有的对象放入一个ArrayList中,要根据id获得对象,那么就写个方法,循环这个arrayList。得到这个id对应的所有的对象比如   class Po
      {
          private long id;
       }   有个方法叫做getPos(id)
     返回就可以了  
     
      

  16.   

    改用泛型,23楼和27楼的想法就可以实现了。import java.util.*;
    class MyClass implements Comparable<MyClass>{
    String name;
    //other....
    MyClass(String name){
    this.name=name;
    }
    //geters ....
    //seters.....
    public int compareTo(MyClass mc){
    return name.compareTo(mc.name); //
    }
    public boolean equals(MyClass mc){
    if(name.equals(mc.name)){
    return true;
    }
    return false;
    }
    public String toString(){
    return name;
    }
    }public class MyCollection<T extends Comparable<T>>{
    private HashMap<String,TreeSet<T>> myMap=new HashMap<String,TreeSet<T>>();
    public void put(String id,T mc){
    TreeSet<T> tree=myMap.get(id);
    if(tree==null){
    TreeSet<T> treeA=new TreeSet<T>();
    treeA.add(mc);
    myMap.put(id,treeA);
    }else{
    tree.add(mc);
    }
    }
    public TreeSet<T> get(String id){
    return myMap.get(id);
    }
    public void printAll(String id){
    TreeSet<T> tree=myMap.get(id);
    for(T mc:tree){
    System.out.println(mc);
    }
    }
    public static void main(String[] args){
    MyCollection<MyClass> myCollection=new MyCollection<MyClass>();
    myCollection.put("1",new MyClass("one"));
    myCollection.put("2",new MyClass("two"));
    myCollection.put("1",new MyClass("oneone"));
    myCollection.put("1",new MyClass("one"));
    myCollection.put("2",new MyClass("twotwo"));
    myCollection.printAll("1");
    MyCollection<String> words=new MyCollection<String>();
    words.put("sh","上海");
    words.put("sh","似乎");
    words.put("kj","会计");
    words.put("sh","嗜好");
    words.put("kj","空间");
    words.put("sh","山河");
    words.put("kj","看见");
    System.out.println("sh:");
    words.printAll("sh");
    System.out.println("kj:");
    words.printAll("kj");

    }}
    //之所以MyClass 实现了Comparable以及用了TreeSet,是为了查找一个对象方便,可以遍历整个myMap来查。但这个问题和你的要求没有关系。
    //用TreeSet还有一意思是相同的对象就没有必要再放进去了。结果:
    F:\java>java  MyCollection
    one
    oneone
    sh:
    上海
    似乎
    嗜好
    山河
    kj:
    会计
    看见
    空间
      

  17.   

    直接使用HashMap<String,String>可以吗?
    Map<String,obj> a = new HashMap<String,obj>
    关键是这个String
    存储的时候用id+标识位,然后拿的时候只要给出id就行啦,只要保证key不同不就好了,不需要用到set或者list
      

  18.   

    你要不怕麻烦就自己重写HashMap--------------------------------
    public HashMap<String,List> getDocApp(ParamsContext pcn) {
    HashMap<String,List> hsm=new HashMap<String,List>();
    Query query=getSession().getNamedQuery("GetTaskApprove");
    query.setParameter("docId", pcn.getDocId());
        List tmp=query.list();     
            String taskId="";
            int fromIndex=0, toIndex=0;
        for (Iterator iter=tmp.iterator(); iter.hasNext();) {
         Object[] result=(Object[])iter.next();
    if(taskId==null||taskId.equals("")){
    taskId=result[0].toString();
    }
    if(result[0].toString().equals(taskId)){
    toIndex++;
    continue;

    }else{
    hsm.put(taskId, tmp.subList(fromIndex, toIndex)); 
    fromIndex=toIndex;
    toIndex++;
    taskId=result[0].toString();
    }
    }
        hsm.put(taskId, tmp.subList(fromIndex, tmp.size())); 
        return hsm;
    }
      

  19.   

    谢谢小虫子同学
    有关系啊,Sh不相当于ID,中文的String不就跟对象一样
    不过25楼的想法我也想过的,不过楼主不是说没关系嘛其实25楼的是我的最初想法,就是搜索的时间代价太大
      

  20.   


    不知道什么算法才能让你惊喜.HashMap算法中,get方法的时间复杂度为O(1)。空间复杂度为O(n)n=你放进去的不重复对象的个数。
    从TreeSet中拿出所有的元素的时间复杂度为O(n)n=相同id的对象个数。
      

  21.   

    类似于这样不行吗?给点伪代码(其中的"sh","kj"相当于你的id)
    long n =0L;
    Map<String,String> loc = new HashMap<String,String>;
    loc.put("sh"+n,"上海");
    n++;
    loc.put("sh"+n,"似乎");
    n++;
    loc.put("sh"+n,"山河");
    n++;
    loc.put("kj"+n,"会计");
    n++;
    loc.put("kj"+n,"看见");
    n++;
    loc.put("kj"+n,"空间");
    n++;
    //只要put后自增就可以
    for(String s:loc.getKeys()){
      if(s.subString(0,2).equals("sh")){
        //这里随便用一个集合或者数组去存放对象
      }
      if(s.subString(0,2).equals("kj")){
        //这里随便用一个集合或者数组去存放对象
      }
    }
    就这样啊,如果只是存放,也就不需要list或者set,map中最多也就是你对象的封装类型和key
    有对应关系的存放最适合的就是map了,不知道还有哪位大大有更好的方法
      

  22.   

    25楼的是节省了空间,但牺牲了时间。
    我有一个大致的想法不知道合不合要求。
    就是用一个ARRAY来装你的所有对象,
    MAP来装(ID, “对象在ARRAY中位序1|| 对象在ARRAY中位序2|| 对象在ARRAY中位序3|| ” )这样通过ID可以取得 “对象在ARRAY中位序1|| 对象在ARRAY中位序2|| 对象在ARRAY中位序3|| ”
    再split, 到array中取你要的对象。
      

  23.   

    此言差矣,ArrayList可以自动扩展长度,即使你真的要放1000,10000个,也不一定在初始化的时候就设置为这么大。另外,ArrayList有个方法叫作trimToSize(); 你可以在不插入数据的时候调用一下
      

  24.   

    用缓存吧 比如说你要申请一千个数据,你可以一百个一百个的申请 分为十次申请 然后在把一百个作为一个整体放到HashMap  最后在内存中虽然也存在1000个地址 但因为他是分为十个整体存在的 相对而言他消耗的内存要小
      

  25.   

    可以尝试用  HashMap  内插一个  list   两个容器嵌套或者直接用 LinkList  效率比较高! 
      

  26.   

    Map<Object,String> 
    key 放 对象
    value 放 id
    这样满足楼主的需要,不会被覆盖了。
      

  27.   


    兄弟你通过 vaule 去找 id???你好猛啊
      

  28.   

    public class MyObject{
      //待保存的对象类。
    }
    public class Collector{
      private Map<Integer,Object> buff = new HashMap<Integer,Object>();
      private List<MyObject> createList(){
        return new LinkedList<MyObject>();
      }
      public void put(Integer id,MyObject obj){
        Object o = buff.get(id);
        if(o==null){
          buff.put(id,obj);
        }else if(o instanceof List)[
          ((List)o).add(obj);
        }else{
          List<MyObject> list = createList();
          list.add((MyObject)o);
          list.add(obj);
          buff.put(id,list);
        }
      }
      public List<MyObject> getMyObjectList(int id){
        Object o = buff.get(id);
        if(o==null)return null;
        else if(o instanceof List){
          return (List)o;
        }else{
          List<MyObject> list = new ArrayList<MyObject>(1);
          list.add((MyObject)o);
          return list;
        }
      }
    }
    List可以换成Set,这样就不会有重复的对象保存到Set当中去。