关于HashMap的put问题

Map map = new HashMap();
map.put("1",new Object());
上面是把new出来的一个对象作为“值”放入了map中。

可是下面的就不理解了:
Object a = new Object();
map.put("1",a);
想问下放入map的到底是new出来的对象的引用(即:a),还是这个对象本身呢?
求解!多谢!


问题补充:stormtoy 写道对象的引用地址


两种方式存储的都是对象的内存地址吗?
可是我做了一个测试:
  byte a[] = new byte[1024*1024*30];   //大小30M
然后把a放入了map,整个程序才循环了7次就报内存溢出的错误了。
如果只是存放的对象的内存地址的话,不应该只能存放7个地址吧&


问题补充:stormtoy 写道我想是因为你运行程序的jvm内存小于你使用的内存,所以出现内存溢出。你应该区分一下值传递和引用传递,值传递是拷贝一个副本到方法里,你方法里面怎么改不会影响到外边,引用传递传递的时对象的地址,调用方法外和内操纵都是同一份地址,所以这个对象改变了,将会影响到外面(因为你外面那个变量指向了这个对象)。




那这两种方法到底有没有区别呢?是不是前者存在map里面的是对象,后这存入map的是对象的引用地址?

回答: 关于HashMap的put问题

  1. 1.hashMap存储的都是地址:
    public class TShashMap {
    	public static void main(String[] args) {
    		Map ts = new HashMap();
    		TSA tsa = new TSA();
    		tsa.setAge(15);
    		tsa.setName("hashMap");
    		ts.put(1, tsa);
    		System.out.println((TSA)ts.get(1));
    		tsa.setAge(18);
    
    		System.out.println((TSA)ts.get(1));
    	}
    }
    class TSA {
    	private String name;
    	private int age;
    	
    	public int getAge() {
    		return age;
    	}
    
    	public void setAge(int age) {
    		this.age = age;
    	}
    
    	public String getName() {
    		return name;
    	}
    
    	public void setName(String name) {
    		this.name = name;
    	}
    	public String toString() {
    		return "name:" + name + " age:" + age;
    	}
    }
    

    楼主跑下上面的i.e就明白了
    2.你给的i.e,内存溢出是由于java虚拟机本身的原因,和内存没有关系。
    只要存入hashmap中的元素在1<<30之内,就OK

有关Java的HashMap的实现的问题

  1. Q

    在Java中,对于HashMap的定义是这样的:

    public class HashMap<K,V>
        extends AbstractMap<K,V>
        implements Map<K,V>, Cloneable, Serializable

     我想知道的是,为什么HashMap的父类AbstractMap已经implements了Map<K,V>接口,而在HashMap的定义中又再一次的声明implements Map<K,V>接口呢,这么做有什么意义呢?

     

    我记得我学长给我的答案是为了更好的面向接口编程,但有些模糊,请大家指导一下;

  2. A
    从编译和运行的角度来说,没有意义。
    但是从读者的角度来说,有意义。

    你可以考虑一下如下场景:
    1,你定义了一个接口,里面有10个抽象方法(接口里面的都是抽象方法)
    2,你有9个抽象类,抽象类1继承接口,实现了1个方法(可以只实现接口的部分方法)
    3,抽象类2继承抽象类1,同时又多实现了一个方法
    4,依次类推,每个抽象类依次继承上面的抽象类,每个都多实现一个方法。
    5,最后你的实现类实现抽象类9,把最后一个未实现的方法实现了。
    那么问题来了
    这时候你读源代码或者文档的时候,你根本不知道你这个类实现了什么接口,如果想知道的话,就要依次把抽象类9,8。。。一直找到抽象类1的时候,你才知道你的这个实现类实际上是实现了你第一步定义的接口,这样是不是对读者很不友好?

    如果每一层都明确声明实现了第一步的接口,那么你看实现类或者任一层次的抽象类的时候,你都不需要再找别的继承关系的类了,因为你可以直接跳到接口去看定义就可以了。

    这就是对读者友好的体现,推荐你以后的开发中注意这一点,代码主要是给人看的,对于机器来说,他只需要2进制字节就可以了。

    #你学长是忽悠你的,愿意钻研是好习惯,希望保持下去!

Mybatis通过HashMap返回多条记录

  1. Q
    1、在Mybatis中写了一个UserMapper.java,一个UserMapper.xml,其中有一个SQL会返回一个hashmap,然后在UserMapper中也是用Map<String,String>接收,但在测试的时候会出现一个返回多条记录的异常。Map不是本来就可以接收多条吗?难道我非得通过List<map>去接收吗?可是我业务层就是需要用Map,也不想在XML通过resultMap去转。有点感觉多此一举一样。有谁碰到过没?
    1、
    public Map<String,Integer> queryUserMenuAuthByUser(String userId) ;
    

    2、<select id="queryUserMenuAuthByUser" parameterType="string" resultType="hashmap">
    select auth_code,menu_code from sys_user_auth where user_id=#{userId}
        </select> 
    这里会报回多条记录如下
    exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne()
  2. A
    谁告诉你返回的第一个字段值就是Map的key,第二个字段值就是Map的Value呢???

    没有任何官方文档有这种写法,凡事不要想当然好不!

    Mybatis返回的Map是这样的一种格式:Map<字段名称,字段值>

    一个Map<字段名,字段值>对象代表一行数据!

    返回多行(多条)数据当然是多个Map啦,多个Map就只好放在List中,比较只能返回一个参数对象!



HashMap<Key,Value>如何按照value(Not Key)值的大小排序?

  1. Q
    HashMap<integer,Double>如何按照value(Not Key)值的大小排序?
    key和value 都市数值类型。
    谢谢!
     
  2. A

    public class EntryComparator implments Comparator<Map.Entry<Integer, Double>> {
      public EntryComparator() {
      }

      public int compare(Map.Entry<Integer, Double> o1, Map.Entry<Integer, Double> o2) {
        return o1.getValue().intValue() - o2.getValue().intValue();
      }
    }

    public class TestHashMapSort() {
      public static void outputSortedHashMap(HashMap<Integer, Double> map) {
        List<Map.Entry<Integer, Double>> list = new ArrayList<Map.Entry<Integer, Double>>(map.entrySet());
        Collections.sort(list, new EntryComparator());
        
        Iterator<Map.Entry<Integer, Double>> i = list.iterator();
        while (i.hasNext()) {
          Map.Entry<Integer, Double> entry = i.next();
          System.out.println("key=" + entry.getKey() + ", value=" + entry.getValue());
        }
      }

      public static void main(String[] args) {
        HashMap<Integer, Double> map = new HashMap<Integer, Double>();
        // ... create you map here...
        outputSortedHashMap(map);
      }
    }

c++hashmap里能否重写判断hashcode是否相等的函数吗?代码如下

  1. Q
    个人理解每个对象分配一个hashcode,先判断是否相等,相等的话再执行比较函数,不相等就不会执行比较函数了。我能否自己写判断hashcode是否相等的方法,让我想要的对象执行比较函数。
    这里我是想在在一个保存坐标的数组里找出所有坐标值相差距离小于3的点集,如(220,119),(220,220),(119,220)是属于一个点集,
    判断依据是abs(a.x - b.x) + abs(a.y - b.y) < 3(a,b是点坐标),每一个元素和其他元素各自进行比较,然后保存点集
    在这程序里我想通过判断hashcode是否相等来找点集,相等依据就是abs(a.x - b.x) + abs(a.y - b.y) < 3,但是hashmap默认相同的对象才有相同的hashcode,所以我没办法,只能让所有点拥有相同的hashcode,就是1,然后进入比较函数里进行点比较,但这样效率太低,比较函数效率远远低于hash函数里判断hashcode是否相等,所有我想问是否能重写判断hashcode相等的函数方法。
    如果不能,我还有什么方法可以实现我的功能,这里考虑点坐标有上万个,之前我用的是嵌套for循环,点坐标两两比较,能实现但是效率太低,别人让我试试hashmap,然后我就碰到这种问题了,hashmap找相同的元素的确可以实现,但是像我这样,一定范围里的点也当作相等的,不知道怎么做了

    #include <opencv2/core/core.hpp>
    #include <opencv2/imgproc/imgproc.hpp>
    #include <opencv2/highgui/highgui.hpp>
    #include <iostream>
    #include <math.h>
    #include <string>

    using std::string;
    #include <unordered_map>
    using std::unordered_multimap;
    using namespace std;
    using namespace cv;

    class StrHash{
    public:
    size_t operator()(const Point a) const {

    return 1;
    }
    };

    class StrCompare{
    public:
    bool operator()(const Point& a, const Point& b) const {

    if (abs(a.x - b.x) + abs(a.y - b.y) < 3) {
    return true;
    }
    else
    return false;
    }

    };

    int main()
    {
    unordered_multimap<Point, int, StrHash, StrCompare> map;
    map.insert(make_pair(Point(30, 120), 1));
    map.insert(make_pair(Point(220, 120), 2));
    map.insert(make_pair(Point(220, 120), 3));
    map.insert(make_pair(Point(220, 120), 4));
    map.insert(make_pair(Point(220, 119), 5));
    map.insert(make_pair(Point(30, 120), 6));
    unordered_multimap<Point, int, StrCompare>::iterator iter1;
    unordered_multimap<Point, int, StrCompare>::iterator iter2;
    for (iter1 = map.begin(); iter1 != map.end();)//遍历
    {
    int num = map.count((*iter1).first);
    iter2 = map.find((*iter1).first);
    if (num > 2) {
    for (int i = 1; i <= num; i++)
    {
    cout << (*iter2).first << "  " << i << endl;
    iter2++;
    }
    iter1++;
    }
    else {

    iter1++;

    }

    }

    }
  2. A
    当你确定要修改的语句时,直接修改原始文件,重建所有即可。

    谢谢赵老师回答,但是可以直接修改源码吗,如果修改源码,我下次再新建一个项目再调用到这个源码,我不就变成上次的功能了,或者说别人导入我的项目,也不能正常运行吧,他的源码没有改,请指导一下,谢谢

hashmap 中的Entry链问题

  1. Q
       引用网上的一段话:引用当程序试图将一个key-value对放入HashMap中时,程序首先根据该 key 的 hashCode() 返回值决定该 Entry 的存储位置:如果两个 Entry 的 key 的 hashCode() 返回值相同,那它们的存储位置相同。如果这两个 Entry 的 key 通过 equals 比较返回 true,新添加 Entry 的 value 将覆盖集合中原有 Entry 的 value,但key不会覆盖。如果这两个 Entry 的 key 通过 equals 比较返回 false,新添加的 Entry 将与集合中原有 Entry 形成 Entry 链,而且新添加的 Entry 位于 Entry 链的头部

    我的疑问是,这段话要怎么理解
    因为当我定义
    map.put(1,"a");
    map.put(1,"b");
    


    此时map的size实际是1,map.get(1)为b也就是说后put的元素把前面的覆盖了。
    所以我想知道的是这个Entry里有多个元素,该怎么理解?
  2. A
    entry应该指的就是键值对吧

Struts2 if标签判断hashMap的值的问题

  1. Q
    List中存放HashMap {["CODE":"1","NAME":"a"],["CODE":"2","NAME":"b"]}
    <s:iterator id="ob" value="list">
    	<s:if test="ob['CODE'] == '1'">
    	<option value="ob['CODE']" selected>ob['CODE']</option>
    	</s:if>
    	<s:else>
    	<option value="ob['CODE']" >ob['CODE']</option>
    	</s:else>
    </s:iterator>
    


    请问这行代码是否有问题
    <s:if test="ob['CODE'] == '1'">

  2. A
    ob['CODE']
    这样写肯定不对吧
    ${ob['CODE'] } 最起码也要这样?
    然后我没试过在list里面放map再拿值判断
    在迭代器里迭代数据的时候判断
    我个人的经验说下
    <s:iterator var="ob" status="status" value="list"> 
    <s:if test="list[#{status.index}]['CODE']=='1'"> 
    利用迭代器的下标在去拿list里面对应的值,然后在判断这样。虽然说不出大道理
    但是解决了我关于格式化时间的时候的错误 你可以借鉴下
    http://blog.csdn.net/javaimport/article/details/8477075

hashmap中的clone为什么是shallow copy of this map

  1. Q
    public Object clone() {
            HashMap<K,V> result = null;
    try {
        result = (HashMap<K,V>)super.clone();
    } catch (CloneNotSupportedException e) {
        // assert false;
    }
            result.table = new Entry[table.length];
            result.entrySet = null;
            result.modCount = 0;
            result.size = 0;
            result.init();
            result.putAllForCreate(this);

            return result;
        }
    新建Entry,把原来Entry中数据放到新的Entry中。新的HashMap与旧的HashMap操作没有关系了,为什么还是shallow?
  2. A
    javadoc上说得很清楚呀
    引用
        /**
         * Returns a shallow copy of this <tt>HashMap</tt> instance: the keys and
         * values themselves are not cloned.

         *
         * @return a shallow copy of this map
         */

java hashmap的一点代码的不解

  1. Q
    请教大牛,我在hashmap的clear方法,看见
    public void clear() {
            modCount++;
            Entry[] tab = table;
            for (int i = 0; i < tab.length; i++)
                tab[i] = null;
            size = 0;
        }
    为什么要用局域的tab来指向全局的table,来清理呢,不直接用table来做?
    这种类似的操作手法经常看见,一直很疑惑?谢谢
  2. A
    clear只对那一瞬间的表进行clear   比如在clear时 进行 扩容 并新增

重写hashcode()方法后,HashMap变成升序?

  1. Q
    public class ObjTest{

    private Integer id;

    public boolean equals(Object obj) {
    if(obj instanceof ObjTest) {
    ObjTest ojb = (ObjTest) obj;
    if(this.id.intValue() == ojb.id.intValue()) {
    return true;
    }
    }
    return false;
    }

    public int hashCode() {
    return id;
    }

    public Integer getId() {
    return id;
    }

    public void setId(Integer id) {
    this.id = id;
    }
    }

    public class HashMapTest {

    private static Map<ObjTest, Integer> map = new HashMap<ObjTest, Integer>();

    private static void init() {
    ObjTest obj1 = new ObjTest();
    obj1.setId(3);
    ObjTest obj2 = new ObjTest();
    obj2.setId(2);
    ObjTest obj3 = new ObjTest();
    obj3.setId(1);

    map.put(obj1, 3);
    map.put(obj2, 2);
    map.put(obj3, 1);

    for(Map.Entry<ObjTest, Integer> e : map.entrySet()) {
    ObjTest obj = (ObjTest) e.getKey();
    System.out.println("key:" + obj.getId());
    }
    }


    public static void main(String[] args) {
    init();
    }
    }

    结果:
    key:1
    key:2
    key:3

    求解?
  2. A
    你为什么要关心hashmap遍历元素时的顺序呢?
    它之所以在这里是升序,完全是因为你改变了hashmap在进行散列是否的逻辑,当你把ObjTest id得值取其他很大的时候,就不一定是升序的了

    关于hashmap进行hash的过程可以参考以下文章:
    http://www.ibm.com/developerworks/cn/java/j-lo-hash/?ca=dgr-cn-javaeye0912