`
齐晓威_518
  • 浏览: 603854 次
  • 性别: Icon_minigender_1
  • 来自: 郑州
社区版块
存档分类
最新评论

无序hashset与hashmap让其有序

 
阅读更多

今天迭代hashmap时,hashmap并不能按照put的顺序,迭代输出值。用下述方法可以:

 

HashMap<String,String> hashmap = new LinkedHashMap<String,String>();

 

HashSet的内容如何排序

方法一:

把HashSet保存在ArrayList里,再用Collections.sort()方法比較

  1. private void doSort(){  
  2.   
  3.         final HashSet<Integer> va = new HashSet<Integer>();  
  4.   
  5.         va.add(2007111315);  
  6.   
  7.         va.add(2007111314);  
  8.   
  9.         va.add(2007111318);  
  10.   
  11.         va.add(2007111313);  
  12.   
  13.         final List<Integer> list = new ArrayList<Integer>();  
  14.   
  15.         for(final Integer value : va){  
  16.   
  17.             list.add(value);  
  18.   
  19.         }  
  20.   
  21.         Collections.sort(list);  
  22.   
  23.         System.out.println(list);  
  24.   
  25.     }  
  26. 方二法:

    把这个HashSet做为构造参数放到TreeSet中就可以排序了

    1. final TreeSet ts = new TreeSet(va);  
    2.   
    3.        ts.comparator();  
    4.   
    5.        System.out.println(ts); 

 

 

 

HashSet和TreeSet 

1. HashSet是通过HashMap实现的,TreeSet是通过TreeMap实现的,只不过Set用的只是Map的key

2. Map的key和Set都有一个共同的特性就是集合的唯一性.TreeMap更是多了一个排序的功能.

3. hashCode和equal()是HashMap用的, 因为无需排序所以只需要关注定位和唯一性即可.

 a. hashCode是用来计算hash值的,hash值是用来确定hash表索引的.

 b. hash表中的一个索引处存放的是一张链表, 所以还要通过equal方法循环比较链上的每一个对象 才可以真正定位到键值对应的Entry.

 c. put时,如果hash表中没定位到,就在链表前加一个Entry,如果定位到了,则更换Entry中的value,并返回旧value

4. 由于TreeMap需要排序,所以需要一个Comparator为键值进行大小比较.当然也是用Comparator定位的.

 a. Comparator可以在创建TreeMap时指定

 b. 如果创建时没有确定,那么就会使用key.com

 

Java中ArrayList和Vector的区别

是的, 这是一个太多太多人遇到过, 讨论过, 解释过的问题.
为了加深自己的记忆, 还是决定写一篇来记录下他.

首先想说的是:
Vector是在Collections API之前就已经产生了的, 而ArrayList是在JDK1.2的时候才作为Collection framework的一部分引入的.  它们都是在内部用一个Obejct[]来存储元素的.

ok, 现在来说他们的差别:
1. 线程安全
Vector是同步的, 而ArrayList不是.
因为Vector是同步的, 所以它是线程安全的.
同样, 因为Vecotr是同步的, 所以他需要额外的开销来维持同步锁, 所以它要比ArrayList要慢.(理论上来说)

当然, 如果你对ArrayList有偏好, 你也可以用Collection.synchronizedList(List)来得到一个线程安全的List.

2. 容量增长
Vector允许用户设置capacityIncrement这样在每次需要扩充数组的size的时候, Vector会尝试按照预先设置的capacityIncrement作为增量来设置, 而ArrayList则会把数组的大小扩大一倍.

比如现在同样一个长度为10的Vector和ArrayList, 我们把Vector的capacityIncrement设为1
那么我们在插入第11个对象的时候, Vector会将长度变成11, 然后分配空间, 然后将对象添加进去, 而ArrayList则会分配20个对象的空间, 然后将对象添加进去.

如果capacityIncrement设为0或者负值, Vector就会做和ArrayList一样, 每次都将数组大小扩大一倍.

3. 性能比较
刚刚在上面已经说过了, 由于Vector是同步的, 而ArrayList不是, 所以Vector的性能要比ArrayList要稍第一点, 用性能换安全嘛.

不过, 据Jack ShiraziOnJava上的一篇文章来看, 似乎这并不是什么问题, 他认为对于现在的JVM来说, 这两个类在同步这个问题上的性能差异, 甚至还不如每次跑测试的时候环境变化引起的差异大.
Consequently Vector is thread-safe, and ArrayList isn't. This makes ArrayList faster than Vector. For some of the latest JVMs the difference in speed between the two classes is negligible: strictly speaking, for these JVMs the difference in speed between the two classes is less than the variation in times obtained from tests comparing the performance of these classes. ---- The Performance of Java's Lists

这样看来, 性能上的差别应该不大.

So, as a conclusion.
结论和网上大多数人得到的结论一样:
在一般情况下, 还是鼓励用ArrayList的, 如果你有同步控制的需要, 那就用Vector吧, 也懒得用Collection.synchronizedList(List)再去转一次了, 除非非这样不可.. 不然还是顺应潮流, 毕竟, 代码是写给人看的. 在无伤大雅的情况下, 按照common的法则来写, 无疑会让看代码的人更快理解. :)

 

java中hashmap和hashtable的区别

1、  继承和实现区别

Hashtable是基于陈旧的Dictionary类的,HashMap是Java 1.2引进的Map接口的一个实现。

2、  线程安全不同

HashTable的方法是同步的,HashMap是未同步,所以在多线程场合要手动同步HashMap。

3、  对null的处理不同

HashTable不允许null值(key和value都不可以),HashMap允许null值(key和value都可以)。即HashTable 不允许null值其实在编译期不会有任何的不一样,会照样执行,只是在运行期的时候Hashtable中设置的话回出现空指针异常。HashMap允许 null值是指可以有一个或多个键所对应的值为null。当get()方法返回null值时,即可以表示 HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键,而应该用containsKey()方法来判断。

4、  方法不同

HashTable有一个contains(Object value),功能和containsValue(Object value)功能一样。
5、HashTable使用Enumeration,HashMap使用Iterator。

6、HashTable中hash数组默认大小是11,增加的方式是 old*2+1。HashMap中hash数组的默认大小是16,而且一定是2的指数。
7、哈希值的使用不同,HashTable直接使用对象的hashCode,代码是这样的:
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
而HashMap重新计算hash值,而且用与代替求模:
int hash = hash(k);
int i = indexFor(hash, table.length);
static int hash(Object x) {
  int h = x.hashCode();
  h += ~(h << 9);
  h ^= (h >>> 14);
  h += (h << 4);
  h ^= (h >>> 10);
  return h;
}
static int indexFor(int h, int length) {
  return h & (length-1);
}

 

区别

Hashtable

Hashmap

继承、实现

Hashtable<K,V> extends Dictionary<K,V> implements Map<K,V>, Cloneable,Serializable

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

 

线程同步

已经同步过的可以安全使用

未同步的,可以使用Colletcions进行同步Map Collections.synchronizedMap(Map m)

对null的处理

 

Hashtable table = new Hashtable();

table.put(null, "Null");

table.put("Null", null);

table.contains(null);

table.containsKey(null);

table.containsValue(null);

后面的5句话在编译的时候不会有异常,可在运行的时候会报空指针异常具体原因可以查看源代码

public synchronized V put(K key, V value) {

     // Make sure the value is not null

  if (value == null) {

         throw new NullPointerException();

}

HashMap map = new HashMap();

map.put(null, "Null");

map.put("Null", null);

map.containsKey(null);

map.containsValue(null);

以上这5条语句无论在编译期,还是在运行期都是没有错误的.

在HashMap中,null可以作为键,这样的键只有一个;可以有一个或多个键所对应的值为null。当get()方法返回null值时,即可以表示 HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键,而应该用containsKey()方法来判断。

增长率

   protected void rehash() {

      int oldCapacity = table.length;

      Entry[] oldMap = table;

      int newCapacity = oldCapacity * 2 + 1;

      Entry[] newMap = new Entry[newCapacity];

      modCount++;

      threshold = (int)(newCapacity * loadFactor);

      table = newMap;

      for (int i = oldCapacity ; i-- > 0 ;) {

          for (Entry<K,V> old = oldMap[i] ; old != null ; ) {

           Entry<K,V> e = old;

           old = old.next;

           int index = (e.hash & 0x7FFFFFFF) % newCapacity;

           e.next = newMap[index];

           newMap[index] = e;

          }

      }

    }

 

void addEntry(int hash, K key, V value, int bucketIndex) {

      Entry<K,V> e = table[bucketIndex];

        table[bucketIndex] = new Entry<K,V>(hash, key, value, e);

        if (size++ >= threshold)

            resize(2 * table.length);

    }

 

哈希值的使用

HashTable直接使用对象的hashCode,代码是这样的:

public synchronized booleancontainsKey(Object key) {

      Entry tab[] = table;

      int hash = key.hashCode();

      int index = (hash & 0x7FFFFFFF) % tab.length;

      for (Entry<K,V> e = tab[index] ; e != null ; e = e.next) {

          if ((e.hash == hash) && e.key.equals(key)) {

           return true;

          }

      }

      return false;

    }

HashMap重新计算hash值,而且用与代替求模

      public boolean containsKey(Object key) {

              Object k = maskNull(key);

              int hash = hash(k.hashCode());

              int i = indexFor(hash, table.length);

              Entry e = table[i];

              while (e != null) {

                  if (e.hash == hash && eq(k, e.key))

                      return true;

                  e = e.next;

              }

              return false;

          }

 

 

 

 

 

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics