java中的几种泛型类——HashSet、HashMap、TreeSet、TreeMap,遍历map,排序,HashTable比较

HashSet

HashSet<E>泛型类在数据组织上类似于数学上的集合,可以进行“交”、“并”、“差”等运算。
HashSet<E>泛型类创建的对象称为集合,如:
    HashSet<E> set =  HashSet<String>();
    那么set就是一个可以存储string类型数据的集合,set可以调用add(String s)方法将string类型的数据添加到集合中。添加到集合中的数据称为集合的元素。集合不允许有相同的元素。也就是说,如果b已经是集合中的元素,那么执行add(b)的操作是无效的。集合对象的初始容量是16字节,装载因子是0.75。也就是说,如果集合添加的元素超过总容量的75%是,集合的容量将增加1倍。
相关运算:
并运算: boolean addAll(HashSet);
交运算:boolean retainAll(HashSet);
差运算:boolean remainAll(HashSet);
参数指定的集合必须与当前集合是同种类型的集合,否则上述方法返回的类型是false。
HashSet<E>泛型类实现了泛型接口Set<E>,而Set<E>接口是Collection<E>接口的子接口。HashSet<E>类中的绝大部分方法都是接口方法的实现。编程时,可以使用接口回调技术,即把HashSet<E>对象的引用赋值给Collection<E>接口变量或Set<E>接口变量,那么接口就可以调用类实现的接口方法。

HashMap

HashMap<K,V>对象成为散列映射对象。散列映射用于存储键-值数据对,允许把任何数量的键-值数据存储在一起。键不可以可重复。如果出现两个数据项的键相同,那么先前散列映射中的键-值对将被替换。散列映射在它需要更多存储容量是会自动增大容量。例如,如果散列映射的装载因子是75%时,它就自动把容量增加到原始容量的2倍。对于数组和链表这两种数据结构,如果要查找它们存储的某个特定的元素却不知道它们的位置,就需要从头开始访问元素知道找到匹配的为止;如果数据结构中包含很多元素,就会浪费时间。这时最好使用散列映射来存储要找的数据,以便检索时可以减少检索的开销。
HashMap<K,V>泛型类创建的对象称为散列映射,如:
     HashMap<K,V> hash = HashMap<String,Student>();
     那么,hash就可以存储键-值对数据,其中的键必须是一个String对象,键对应的值必须是Student对象。hash可以调用
public V put(K key, V value)方法将键-值对存储在散列映射中,同时返回键所对应的值。
   遍历散列映射的方法有如下四种:
public static void main(String[] args) {
	Map<String, String> map = new HashMap<String, String>();
	map.put("1", "value1");
	map.put("2", "value2");
	map.put("3", "value3");

	// 第一种:普遍使用,二次取值
	System.out.println("通过Map.keySet遍历key和value:");
	for (String key : map.keySet()) {
		System.out.println("key= " + key + " and value= " + map.get(key));
	}

	// 第二种
	System.out.println("通过Map.entrySet使用iterator遍历key和value:");
	Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
	while (it.hasNext()) {
		Map.Entry<String, String> entry = it.next();
		System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
	}

	// 第三种:推荐,尤其是容量大时
	System.out.println("通过Map.entrySet遍历key和value");
	for (Map.Entry<String, String> entry : map.entrySet()) {
		System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
	}

	// 第四种
	System.out.println("通过Map.values()遍历所有的value,但不能遍历key");
	for (String v : map.values()) {
		System.out.println("value= " + v);
	}
}
HashMap<E>泛型类是实现泛型接口Map<E>。

TreeSet

TreeSet<E>类是实现Set接口的类。
TreeSet<E>泛型类创建的对象称为树集,如:
     TreeSet<Student> tree = TreeSet<Student>();
     那么tree就是一个可以存储Student对象的集合,tree可以调用add(Student s)方法将Student对象添加到树集中。树集采用树结构存储数据,树集节点的排列和链表不同,不按添加的先后顺序顺序排列。树集采用add()方法增加节点,节点会按其存放的数据的“大小”顺序一层一层地依次排序,同一层的节点按“大小”顺序递增排列,下一层的比上一层的小树集是一个有序集合

TreeMap

TreeMap类实现了Map接口,TreeSet类提供了按排序顺序存储键-值对的有效手段。 TreeMap保证它的元素按key升序排列。
构造函数有2种:
   TreeMap<K,V>()按照关键字key的大小顺序来对键-值对进行升序排序,key的顺序是按其字符串表示的字典顺序。
   TreeMap<K,V>(Comparator<K> comp)关键字key的大小顺序按照Comparator接口规定的大小顺序对树映射中的键-值对进行排序,即可以升序,也可以降序,取决于里面重写的方法。
   下面是一个排序的例子:
package test;

import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

public class Sort {

	public static void main(String[] args) {
		System.out.println("开始:");
		Person person1 = new Person("马先生", 220181);
		Person person2 = new Person("李先生", 220193);
		Person person3 = new Person("王小姐", 220186);
		Map<Number, Person> map = new HashMap<Number, Person>();
		map.put(person1.getIdCard(), person1);
		map.put(person2.getIdCard(), person2);
		map.put(person3.getIdCard(), person3);
		System.out.println("由HashMap类实现的Map集合,无序:");
		for (Iterator<Number> it = map.keySet().iterator(); it.hasNext();) {// 遍例集合
			Person person = map.get(it.next());
			System.out.println(person.getIdCard() + " " + person.getName());
		}
		System.out.println("由TreeMap类实现的Map集合,键对象升序:");
		TreeMap<Number, Person> treeMap = new TreeMap<Number, Person>();
		treeMap.putAll(map);
		for (Iterator<Number> it = treeMap.keySet().iterator(); it.hasNext();) {// 遍例集合
			Person person = treeMap.get(it.next());
			System.out.println(person.getIdCard() + " " + person.getName());
		}
		System.out.println("由TreeMap类实现的Map集合,键对象降序:");
		TreeMap<Number, Person> treeMap2 = new TreeMap<Number, Person>(
				Collections.reverseOrder());// 初始化为反转排序
		treeMap2.putAll(map);
		for (Iterator it = treeMap2.keySet().iterator(); it.hasNext();) {// 遍例集合
			Person person = (Person) treeMap2.get(it.next());
			System.out.println(person.getIdCard() + " " + person.getName());
		}
		System.out.println("结束!");
	}
}

class Person {
	private String name;
	private long idCard;

	public Person(String name, long idCard) {
		this.name = name;
		this.idCard = idCard;
	}

	public long getIdCard() {
		return idCard;
	}

	public void setIdCard(long idCard) {
		this.idCard = idCard;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

     输出结果为:
开始:
由HashMap类实现的Map集合,无序:
220186 王小姐
220181 马先生
220193 李先生
由TreeMap类实现的Map集合,键对象升序:
220181 马先生
220186 王小姐
220193 李先生
由TreeMap类实现的Map集合,键对象降序:
220193 李先生
220186 王小姐
220181 马先生
结束!

TreeMap也可以用一个简单的方法使它按键key降序排列:
TreeMap<Double, double[]> sortMap = new TreeMap<Double, double[]>(<span style="color:#ff0000;">Collections.reverseOrder()</span>);// 初始化为翻转排序

所以,如果map需要按键排序,把键-值对放在TreeMap即可

map中按值排序则需要重写Comparator方法,如下的例子:
 List<Map.Entry<Integer, Double>> entrySet = new
		 ArrayList<Map.Entry<Integer, Double>>(map.entrySet());
		 System.out.println("排序前的特征值: " + entrySet);
		 Collections.sort(entrySet,new <span style="color:#ff0000;">Comparator</span><Map.Entry<Integer, Double>>() {
		 public int compare(Entry<Integer, Double> o1,
		 Entry<Integer, Double> o2) {
		 return o2.getValue().compareTo(o1.getValue());//<span style="color:#ff0000;">此处对象o1和对象o2的先后顺序可决定是按升序还是按降序排序</span>
		 }
		 });

Map常用操作

         1) 添加操作:
        V put(K key, V value):如果key已存在,在关联后,返回替换前该key对应的value值,如果不存在,则返回null;
        void putAll(Map t):将来自特定映像的所有元素添加给该映射。
    2) 删除操作:
        V remove(Object key):从此映射中移除指定键的映射关系(如果存在),不存在则返回null;
        void clear() :从此映射中移除所有映射关系. 
    3) 查询操作:
        V get(key): 获得与关键字key相关的值,并且返回与关键字key相关的对象,如果没有该关键字,则返回null;判断key是否存在,可以通过返回值是否等于null
        boolean containsKey(key): 判断映像中是否存在关键字key;
        boolean containsValue(Object value): 判断映像中是否存在值value;
        int size(): 返回当前映像中映射的数量;
        boolean isEmpty(): 判断映像中是否有任何映射.
        Collection values():返回映像中所有value值的集由于值多个,用Collection集合,对其操作可以使用Collection基本方法.

 

HashMap和HashTable的区别:

      1) HashTable:底层是哈希表数据结构;hash值直接使用对象的hashCode;不可以存入null键和null值;hash数组默认大小是11,增加的方式是 old*2+1;线程同步,在多线程并发的环境下,可以直接使用Hashtable;JDK1.0效率低;
   2) HashMap:继承自Dictionary类,底层是哈希表数据结构;重新计算hash值;可以存入null键和null值;hash数组的默认大小是16而且一定是2的指数;线程不同步,在多线程并发的环境下,要自己增加同步处理;JDK1.2效率高。
    一般情况下,HashMap能够比Hashtable工作的更好、更快,主要得益于它的散列算法,以及没有同步。应用程序一般在更高的层面上实 现了保护机制,而不是依赖于这些底层数据结构的同步,因此,HashMap能够在大多应用中满足需要。推荐使用HashMap,如果需要同步,可以使用同步工具类将其转换成支持同步的HashMap。

LinkedHashMap保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.也可以在构造时用带参数,按照应用次数排序。在遍历的时候会比HashMap慢,不过有种情况例外,当HashMap容量很大,实际数据较少时,遍历起来可能会比LinkedHashMap慢,因为LinkedHashMap的遍历速度只和实际数据有关,和容量无关,而HashMap的遍历速度和他的容量有关。

有并发访问的时候用ConcurrentHashMap,效率比用锁的HashMap好 功能上可以,但是毕竟ConcurrentHashMap这种数据结构要复杂些,如果能保证只在单一线程下读写,不会发生并发的读写,那么就可以试用HashMap。ConcurrentHashMap读不加锁 

——————————————————————————————————————————————————————
写博经验尚浅,请各位多多指教。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值