Linux sort的选项(参数)与用法举例
2011-07-15 20:12
495 查看
package test.shenli.java.util; import java.util.Enumeration; /** * Object that wraps entries in the hash-table * @author Morten Jorgensen * 哈希表实体类 */ class HashtableEntry { int hash; //哈希值 Object key; //键对象 Object value; //值对象 HashtableEntry next; //链表结构,next指向下一个实体 /** * 实现clone方法,复制自己(原型模式) */ protected Object clone() { HashtableEntry entry = new HashtableEntry(); entry.hash = hash; entry.key = key; entry.value = value; //如果next不为空,将entry的next指向next的副本,在调用next.clone时 //会继续判断next.next,并继续复制下去,最终会复制整个链表,所以改变 //clone,将不会更改原对象 entry.next = (next != null) ? (HashtableEntry)next.clone() : null; return entry; } } /** * The main hash-table implementation */ public class Hashtable { private transient HashtableEntry table[]; // hash-table entries 实体数组 private transient int count; // number of entries 实体数组数量 private int threshold; // current size of hash-tabke 阀值 private float loadFactor; // load factor 负载因子 /** * Constructs a new, empty hashtable with the specified initial * capacity and the specified load factor. * @param initialCapacity: 初始容量 * @param loadFactor 负载因子 */ public Hashtable(int initialCapacity, float loadFactor) { if (initialCapacity <= 0) initialCapacity = 11; //最小初始容量为1 if (loadFactor <= 0.0) loadFactor = 0.75f; //最小负载因子是0.75 this.loadFactor = loadFactor; table = new HashtableEntry[initialCapacity]; //使用初始容量,初始化实体数组 threshold = (int)(initialCapacity * loadFactor); //初始化阀值=初始容量x负载因子 } /** * Constructs a new, empty hashtable with the specified initial capacity * and default load factor. * 重载构造函数(一个参数) * @param initialCapacity 初始容量 */ public Hashtable(int initialCapacity) { this(initialCapacity, 0.75f); } /** * Constructs a new, empty hashtable with a default capacity and load * factor. * 重载构造函数(没有参数) */ public Hashtable() { this(101, 0.75f); } /** * Returns the number of keys in this hashtable. * @Return 返回实体数组数量 */ public int size() { return count; } /** * Tests if this hashtable maps no keys to values. * @return 返回实体数组数量是否为0 */ public boolean isEmpty() { return count == 0; } /** * Returns an enumeration of the keys in this hashtable. * 使用HashtableEnumerator构造一个keys为true的枚举类 * (在next的时候根据keys为tru或false返回e.key或e.value) */ public Enumeration keys() { return new HashtableEnumerator(table, true); } /** * Returns an enumeration of the values in this hashtable. * Use the Enumeration methods on the returned object to fetch the elements * sequentially. * 使用HashtableEnumerator构造一个keys为false的枚举类 * (在next的时候根据keys为tru或false返回e.key或e.value) */ public Enumeration elements() { return new HashtableEnumerator(table, false); } /** * Tests if some key maps into the specified value in this hashtable. * This operation is more expensive than the <code>containsKey</code> * method. * 判断一个值是否在实体数组的value里 */ public boolean contains(Object value) { //入参为空,直接报空指针异常 if (value == null) throw new NullPointerException(); int i; HashtableEntry e; HashtableEntry tab[] = table; //循环数组比对值是否相同 for (i = tab.length ; i-- > 0 ;) { for (e = tab[i] ; e != null ; e = e.next) { if (e.value.equals(value)) { return true; } } } return false; } /** * Tests if the specified object is a key in this hashtable. */ public boolean containsKey(Object key) { HashtableEntry e; HashtableEntry tab[] = table; /** * Object.HashCode * 返回该对象的哈希码值。支持此方法是为了提高哈希表(例如 java.util.Hashtable 提供的哈希表)的性能。 * hashCode 的常规协定是: * * 在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。 * 从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。 * 如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。 * 如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不 要求一定生成不同的整数结果。 * 但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。 * * 实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。 *(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。) */ //调用Object的hashCode方法(native) int hash = key.hashCode(); //-1 & 0x7FFFFFFF == Integer.MAX_VALUE int index = (hash & 0x7FFFFFFF) % tab.length; for (e = tab[index] ; e != null ; e = e.next) if ((e.hash == hash) && e.key.equals(key)) return true; return false; } /** * Returns the value to which the specified key is mapped in this hashtable. */ public Object get(Object key) { HashtableEntry e; HashtableEntry tab[] = table; int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % tab.length; //搜索链表上所有的值 for (e = tab[index] ; e != null ; e = e.next) if ((e.hash == hash) && e.key.equals(key)) return e.value; return null; } /** * Rehashes the contents of the hashtable into a hashtable with a * larger capacity. This method is called automatically when the * number of keys in the hashtable exceeds this hashtable's capacity * and load factor. * 将Hashtable的内容到一个大容量的哈希表。自动调用该方法时,在哈希表中的键的数目超过了哈希表的容量和加载因子。 */ protected void rehash() { HashtableEntry e, old; int i, index; int oldCapacity = table.length; HashtableEntry oldTable[] = table; int newCapacity = oldCapacity * 2 + 1; HashtableEntry newTable[] = new HashtableEntry[newCapacity]; threshold = (int)(newCapacity * loadFactor); table = newTable; //粗略的理解是,根据新的容量计算新的hashCode后,作为数组下标,重建数组 for (i = oldCapacity ; i-- > 0 ;) { for (old = oldTable[i] ; old != null ; ) { e = old; old = old.next; index = (e.hash & 0x7FFFFFFF) % newCapacity; e.next = newTable[index]; newTable[index] = e; } } } /** * Maps the specified <code>key</code> to the specified * <code>value</code> in this hashtable. Neither the key nor the * value can be <code>null</code>. * <p> * The value can be retrieved by calling the <code>get</code> method * with a key that is equal to the original key. */ public Object put(Object key, Object value) { // Make sure the value is not null if (value == null) throw new NullPointerException(); // Makes sure the key is not already in the hashtable. HashtableEntry e; HashtableEntry tab[] = table; int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % tab.length; for (e = tab[index] ; e != null ; e = e.next) { if ((e.hash == hash) && e.key.equals(key)) { Object old = e.value; e.value = value; return old; } } // Rehash the table if the threshold is exceeded if (count >= threshold) { rehash(); return put(key, value); } // Creates the new entry. //如果key的hashCode相同,那么就往链表里追加一个对象!!! e = new HashtableEntry(); e.hash = hash; e.key = key; e.value = value; e.next = tab[index]; tab[index] = e; count++; return null; } /** * Removes the key (and its corresponding value) from this * hashtable. This method does nothing if the key is not in the hashtable. */ public Object remove(Object key) { HashtableEntry e, prev; HashtableEntry tab[] = table; int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % tab.length; for (e = tab[index], prev = null ; e != null ; prev = e, e = e.next) { if ((e.hash == hash) && e.key.equals(key)) { if (prev != null) prev.next = e.next; else tab[index] = e.next; count--; return e.value; } } return null; } /** * Clears this hashtable so that it contains no keys. */ public void clear() { HashtableEntry tab[] = table; for (int index = tab.length; --index >= 0; ) tab[index] = null; count = 0; } /** * Returns a rather long string representation of this hashtable. * Handy for debugging - leave it here!!! */ public String toString() { int i; int max = size() - 1; StringBuffer buf = new StringBuffer(); Enumeration k = keys(); Enumeration e = elements(); buf.append("{"); for (i = 0; i <= max; i++) { String s1 = k.nextElement().toString(); String s2 = e.nextElement().toString(); buf.append(s1).append('=').append(s2); if (i < max) buf.append(", "); } buf.append("}"); return buf.toString(); } /** * A hashtable enumerator class. This class should remain opaque * to the client. It will use the Enumeration interface. */ class HashtableEnumerator implements Enumeration { boolean keys; int index; HashtableEntry table[]; HashtableEntry entry; HashtableEnumerator(HashtableEntry table[], boolean keys) { this.table = table; this.keys = keys; this.index = table.length; } public boolean hasMoreElements() { if (entry != null) { return true; } while (index-- > 0) { if ((entry = table[index]) != null) { return true; } } return false; } public Object nextElement() { if (entry == null) { while ((index-- > 0) && ((entry = table[index]) == null)); } if (entry != null) { HashtableEntry e = entry; entry = e.next; return keys ? e.key : e.value; } return null; } } }
相关文章推荐
- [Linux]linux mount命令-o参数sync选项的用法
- linux sort命令参数及用法
- Linux的sort、uniq、wc命令常用参数举例解析
- linux sort命令参数及用法详解
- linux sort命令参数及用法详解---linux将文本文件内容加以排序命令
- linux系统下的命令sort与uniq的参数选项详解
- linux sort命令的用法
- linux sort 命令详解(看完你就会sort用法了)
- linux 下chattr 用法参数说明
- linux sort的用法
- linux alias命令参数及用法详解--linux定义命令别名alias
- linux id命令参数及用法详解(linux查看当前登陆用户uid,gid)
- linux usermod命令参数及用法详解(linux修改用户账号信息命令)
- linux dmesg命令参数及用法详解(linux显示开机信息命令)
- linux chkconfig命令参数及用法详解--linux系统服务设置命令
- linux chmod命令参数及用法详解--文件文件夹权限设定命令
- linux 2.6内核epoll用法举例说明
- linux uname命令参数及用法详解(linux查看系统信息命令)
- Linux中grep命令参数及用法详解---linux管道命令grep
- linux grep命令参数及用法详解---linux管道命令grep