Java集合

Java 集合

Collection<<interface>>
├List<<interface>>
│├LinkedList
│├ArrayList
│└Vector
 └Stack
└Set<<interface>>

└HashSet

Map<<interface>>
├Hashtable
├HashMap
└WeakHashMap

1.    Collection Collections的区别

java.util.Collection 是一个集合接口。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式。
  java.util.Collections
是针对集合类的一个帮助类,他提供一系列静态方法实现对各种集合的搜索、排序、线程安全化等操作

class Demo {
	public Demo() {}
	public static void main(String[] args){
		ArrayList c = new ArrayList();
		for (int i = 0; i < 3; i++) {
			c.add(new Integer(i));
		}
		c.add("11");
		c.add("22");
		c.add("33");
		Iterator it = c.iterator();
		System.out.println("排序前的输出:\n");
		for (int i = 0; i < c.size(); i++) {
			System.out.println("" + c.get(i));
		}
		Collections.shuffle(c, new Random());
		System.out.println("排序后的输出:\n");
		while (it.hasNext()) {
			System.out.println("" + it.next());
		}
	}
}

 

2.    HashMapHashtable的区别

Hashtable继承自Dictionary, size()表示包含了多少元素;isEmpty()判断是否包含了元素;put(Object key, Object value)添加一个值;get(Object key)获得与某个键对应的值;而remove(Object Key)从列表中删除键-值对。还可以使用枚举技术:keys()产生对键的一个枚举(Enumeration);而elements()产生对所有值的一个枚举。这便是一个Dictionary(字典)的全部。

(1) 继承和实现区别

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

(2) 线程安全不同

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

(3) 对null的处理不同

HashTable不允许null(keyvalue都不可以),HashMap允许null(keyvalue都可以)

HashTable 不允许null,编译期不会检查,运行期会出现空指针异常。HashMap允许 null值是指可以有一个或多个键所对应的值为null。当get()方法返回null值时,即可以表示 HashMap中没有该键,也可以表示该键所对应的值为null。因此,在HashMap中不能由get()方法来判断HashMap中是否存在某个键,而应该用containsKey()方法来判断。

(4) 方法不同   HashMapHashtablecontains方法去掉了,改成containsvaluecontainsKey

(5) HashTable使用EnumerationHashMap使用Iterator

(6) HashTable中hash数组默认大小是11,增加的方式是 old*2+1HashMaphash数组的默认大小是16,而且一定是2的指数。

HashTable测试

public static void main(String ar()[]) {
	Hashtable hash = new Hashtable();
	hash.put("abc", "1");
	hash.put("ddd", "1");
	hash.put("asdf", "2");
	// hash.put("asdfsad", null); NullPointerException
	Enumeration enumkey = hash.keys();
	while (enumkey.hasMoreElements()) {
		String str = (String) enumkey.nextElement();
		System.out.println(str + " --- " + hash.get(str));
		if ("1".equals(hash.get(str)))
			hash.remove(str);
	}
	System.out.println("asdf:" + hash.get("asdf"));
	enumkey = hash.elements();
	while (enumkey.hasMoreElements()) {
		String str = (String) enumkey.nextElement();
		System.out.println(str );
	}
} 

HashMap测试

public static void main(String[] args) {
	// 在HashMap中的对象是无序的
	HashMap hm = new HashMap();
	hm.put("a", "wpskl 1");
	hm.put("b", "wpskl 3");
	hm.put("c", "wpskl 5");
	// 测试是否包含关键字"a"
	System.out.println(hm.containsKey("a"));//true
	System.out.println(hm.containsKey("d"));//false
	System.out.println(hm.get("a"));		//wpskl 1
	System.out.println(hm.entrySet());		
	//[a=wpskl 1, c=wpskl 5, b=wpskl 3]
	Iterator it = hm.entrySet().iterator();
	while (it.hasNext()) {
		System.out.println(it.next());
		//a=wpskl 1,c=wpskl 5,b=wpskl 3
	}
	// Set keySet()返回关键字的集合
	it = hm.keySet().iterator();
	while (it.hasNext()) {
		System.out.println(hm.get(it.next()));
		//get(key)返回关键字对应的值 
	 }
	// Collection values()返回值的集合
	it = hm.values().iterator();
	while (it.hasNext()) {
		System.out.println(it.next());
		//wpskl 1,wpskl 5,wpskl 3
	}
}

3.    List总结(ArrayList,Vector, LinkedList)

List除了具有Collection接口必备的iterator()方法外,它还提供一个listIterator()方法,返回一个ListIterator接口,和标准的Iterator接口相比,ListIterator多了一些add()之类的方法,允许添加,删除,设定元素,还能向前或向后遍历

ArrayList,Vector, LinkedList的存储性能和特性:

1ArrayList是最常用的List实现类,内部通过数组实现,它允许对元素进行快速随机访问。当数组大小不满足时会增加存储能力(默认大小是10,每次扩充为原来的1.5倍),将已有数组数据复制到新的存储空间中。当从ArrayList的中间位置插入或者删除元素时,需要对数组进行拷贝,移动,代价比较高。因此,它适合随即查找和遍历,不适合插入合删除。
   
2VectorArrayList一样,也是通过数组实现的。它支持线程的同步,避免多线程同时写引起的不一致性。但实现同步需要很高的花费,因此,访问它比访问ArrayList慢。

List list = Collections.synchronizedList(new ArrayList());//创建同步的ArrayList
   
3LinkedList使用双向链表实现存储,很适合数据的动态插入和删除,随即访问和遍历速度比较慢。另外,它还提供了List没有定义的方法,专门用于操作表头和表尾元素,可以当作堆栈、队列和双向队列使用。

4)堆栈类继承VectorStack提供5个额外的方法使得Vector得以被当作堆栈使用。基本的pushpop方法,还有peek方法得到栈顶的元素,empty方法测试堆栈是否为空,search方法检测一个元素在堆栈中的位置。

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Stack;
import java.util.Vector;
//演示List的使用 List是能维护元素的次序,它允许元素重复
public class TestList {
	//初始化一个List
	public static void init(List list) {
		if (list != null) {
			list.add("aaa");
			list.add("ccc");
			list.add("bbb");
			list.add("eee");
			list.add("ddd");
		}
	}
	//输出List的内容
	public static void output(List list) {
		if (list != null) {// 根据列表下标遍历,使用list.size()获取列表中元素的个数
			for (int i = 0; i < list.size(); i++) {
				System.out.print(list.get(i) + "  ");
			}
			// 或者用迭代器遍历
			Iterator it = list.iterator();
			Object value = null;
			while (it.hasNext()) {
				value = it.next();
				// System.out.println(value);
			}//或
			for(Iterator i=list.iterator();i.hasNext();){
				value=i.next();
			}
		}
	}
	//使用ArrayList
	public static void testArrayList() {
		List list = new ArrayList();
		init(list);
		System.out.println("使用ArrayList: ");
		output(list);
	}
	//使用Vector
	public static void testVector() {
		List list = new Vector();
		init(list);
		System.out.println("使用Vector: ");
		output(list);
	}
	//使用LinkedList
	public static void testLinkedList() {
		List list = new LinkedList();
		init(list);
		System.out.println("使用LinkedList: ");
		output(list);
	}
	public static void main(String[] args) {
		TestList.testArrayList();
		TestList.testVector();
		TestList.testLinkedList();
		List list = new ArrayList();
		init(list);
		// List支持元素重复
		list.add("aaa");
		list.add("bbb");
		System.out.println("插入元素aaa, bbb后:");
		output(list); //在末尾添加
		list.add(1, "fff");// 指定元素插入的位置
		System.out.println("在下标为1处插入fff后:");
		output(list);
		List list2 = new ArrayList();
		list2.add("ggg");
		list2.add("hhh");
		// 将另一列表中的元素插入到列表中
		list.addAll(list2);
		System.out.println("添加list2的元素后:");
		output(list);
		// 判断列表是否包含某一元素
		// 通过元素的equals方法,判断元素是否相等
		System.out.println("list包含aaa? " + list.contains("aaa"));
		// 判断列表中是否包含了另外一个列表中的所有元素。
		System.out.println("list包含list2中的所有元素? " + list.containsAll(list2));
		// 定位一个元素在列表中最先出现的位置System.out.println("aaa在list中第一次出现的位置: " + list.indexOf("aaa"));
		// 定位一个元素在列表中最后出现的位置System.out.println("aaa在list中最后一次出现的位置: " + list.lastIndexOf("aaa"));
		list.set(2, "xxx");// 更新列表中某个位置的元素值
		System.out.println("更新位置为2的元素为xxx后:");
		output(list);
		// 删除列表中的某个元素,只删除第一次出现的那个
		list.remove("aaa");
		System.out.println("删除元素aaa后:");
		output(list);
		list.remove(1); // 删除列表中指定位置的元素
		System.out.println("删除下标为1的元素后:");
		output(list);
		// 删除列表中的其他元素,只保留另一个列表中包含的元素
		list.retainAll(list2);
		System.out.println("删除除list2包含的以外的元素后:");
		output(list);
		// 删除列表中在另一列表中也包含了的元素
		list.removeAll(list2);
		System.out.println("删除list2包含的元素后:");
		output(list);
		list.clear();// 清空列表
		// 判断列表中是否有数据
		System.out.println("清空List后" + list.isEmpty());
		init(list);
		// 用列表中的某些元素构造一个新的列表
		list2 = list.subList(1, 3);
		System.out.println("用list的第1个到第3个元素构造一个新的List:");
		output(list2);
		// 用List特有的遍历器ListIterator遍历列表
		// 与普通的Iterator不用,它允许两个方向遍历列表
		ListIterator listIt = list.listIterator();
		System.out.println("正向遍历列表");
		while (listIt.hasNext()) {
			System.out.print(listIt.next());
		}
		System.out.println("反向遍历列表");
		while (listIt.hasPrevious()) {
			System.out.print(listIt.previous());
		}
		// 也可以使用ListIterator从List中间插入和删除元素,
		// 只能在遍历器当前位置添加和删除。
		listIt.add("newadd");
		System.out.println("ListIterator往列表中添加元素newadd后: ");
		output(list);
		listIt.next();
		listIt.remove();
		System.out.println("用ListIterator删除列表中元素后: ");
		output(list);
		// LinkedList自定义的方法
		LinkedList linklist = new LinkedList();
		init(linklist);
		linklist.addFirst("fff");// 添加元素到列表头
		System.out.println("把fff放到列表头后:");
		output(linklist);
		// 添加元素到列表尾
		linklist.addLast("eee");
		System.out.println("把eee放到列表尾后:");
		output(linklist);
		// 获取表头元素
		System.out.println("列表头元素:" + linklist.getFirst());
		// 获取表尾元素
		System.out.println("列表尾元素:" + linklist.getLast());
		linklist.removeFirst();// 删除列表头的元素
		System.out.println("删除列表头元素后:");
		output(linklist);
		linklist.removeLast();// 删除列表尾的元素
		System.out.println("删除列表尾元素后:");
		output(linklist);
		// 堆栈Stack类,它继承自Stack类
		Stack myStack = new Stack();
		myStack.push("aaa");// 插入元素,是插入到尾部
		myStack.push("bbb");
		myStack.push("ccc");
		myStack.push("ddd");
		myStack.push("aaa");
		myStack.push("ddd");
		System.out.println("堆栈中的元素是: ");
		output(myStack);
		System.out.println("堆栈尾部元素: " + myStack.peek());
		System.out.println("弹出堆栈尾部元素: " + myStack.pop());
	}
}

4.    Map

Map接口提供3种集合的视图:

mapkey不能够重复,value可以

1key-value映射集合 entrySet() 返回包含映射的Set视图。Set中的每个元素都是一个Map.Entry对象,可以使用getKey()getValue()方法(还有一个setValue() 方法)访问后者的键元素和值元素

2key集合 keySet() 包含键的 Set 视图。删除 Set 中的元素还将删除 Map 中相应的映射(键和值)

3value集合,values() 是值的 Collection 视图。删除 Collection 中的元素还将删除 Map 中相应的映射(键和值)

我们还必须获得一个Iterator对象,进而取得相应的key-value映射、keyvalue

Iterator keyValuePairs = aMap.entrySet().iterator();

Iterator keys = aMap.keySet().iterator();//keys.remove();删除当前键值对

Iterator values = aMap.values().iterator();//values.remove();删除当前键值对

Map增删方法

clear() Map 中删除所有映射 

remove(Object key) Map 中删除键和关联的值 

put(Object key, Object value) 将指定值与指定键相关联

Map访问方法

get(Object key) 返回与指定键关联的值 

containsKey(Object key) 如果 Map 包含指定键的映射,则返回true

containsValue(Object value) 如果此 Map 将一个或多个键映射到指定值,则返回 true

isEmpty() 如果 Map 不包含键-值映射,则返回 true 

size() 返回 Map 中的键-值映射的数目

 

 

 

5.    集合排序

listsetmap都是可以使用collections.sort()排序,http://lavasoft.blog.51cto.com/62575/68380

Java API针对集合类型排序提供了两种支持:

java.util.Collections.sort(java.util.List)
java.util.Collections.sort(java.util.List, java.util.Comparator)

 

 实现Comparable接口

/*实现Comparable接口*/

// 要排序的元素对象 
 
public class Cat implements Comparable<Cat> { 
    private int age; 
    private String name; 
    public Cat(int age, String name) { 
        this.age = age; 
        this.name = name; 
    } 
    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 "Cat{" + 
                "age=" + age + 
                ", name='" + name + '\'' + 
                '}'; 
    } 
    public int compareTo(Cat o) { 
        return this.getAge() - o.getAge(); 
    } 
}

 

 实现个性化排序测试

import java.util.*; 
//通过实现Comparable接口实现个性化排序测试 
public class TestComparable { 
    public static String outCollection(Collection coll) { 
        StringBuffer sb = new StringBuffer(); 
        for (Object obj : coll) { 
            sb.append(obj + "\n"); 
        } 
        System.out.println(sb.toString()); 
        return sb.toString(); 
    } 
    public static void main(String args[]) { 
        test(); 
        test2(); 
    } 
    public static void test() { 
        System.out.println("----------test()---------"); 
        System.out.println("升序排序测试:"); 
        List<Cat> listCat = new ArrayList<Cat>(); 
        Cat cat1 = new Cat(34, "hehe"); 
        Cat cat2 = new Cat(12, "haha"); 
        Cat cat3 = new Cat(23, "leizhimin"); 
        Cat cat4 = new Cat(13, "lavasoft"); 
        listCat.add(cat1); 
        listCat.add(cat2); 
        listCat.add(cat3);
        System.out.println("原集合为:"); 
        outCollection(listCat); 

        System.out.println("调用Collections.sort(List<T> list)排序:"); 
        Collections.sort(listCat); 
        outCollection(listCat); 
        System.out.println("逆序排列元素:"); 
        Collections.sort(listCat, Collections.reverseOrder()); 
        outCollection(listCat); 
        System.out.println("再次逆序排列元素:"); 
        Collections.reverse(listCat); 
        outCollection(listCat); 
        System.out.println("添加一个元素后输出集合:"); 
        listCat.add(cat4); 
        outCollection(listCat); 
        System.out.println("排列后输出:"); 
        Collections.sort(listCat); 
        outCollection(listCat); 
    }

 

针对数组的排序测试 

 public static void test2(){ 
        String[] strArray = new String[] {"z", "a", "C"}; 
        System.out.println("----数组转换为列表-------"); 
        List<String> list = Arrays.asList(strArray); 
        outCollection(list); 
        System.out.println("----列表转换为数组(1)-----"); 
        String[] strArrayNew1 = list.toArray(strArray); 
        for(String str:strArrayNew1){ 
            System.out.println(str); 
        } 
        System.out.println("---列表转换为数组(2)-----"); 
        String[] strArrayNew2 = (String[]) list.toArray(); 
        for(String str:strArrayNew2){ 
            System.out.println(str); 
        } 
        System.out.println("----顺序排序列表------"); 
        Collections.sort(list); 
        outCollection(list); 
        System.out.println("---按String实现的Comparator对象   String.CASE_INSENSITIVE_ORDER排序----"); 
        Collections.sort(list, String.CASE_INSENSITIVE_ORDER); 
        outCollection(list); 
        System.out.println("-----倒序排序列表------"); 
        Collections.sort(list, Collections.reverseOrder()); 
        outCollection(list); 

        System.out.println("-----按String实现的Comparator对象String.CASE_INSENSITIVE_ORDER排序----"); 
        Collections.sort(list, String.CASE_INSENSITIVE_ORDER); 
        outCollection(list); 

        System.out.println("-----反转列表元素的顺序------"); 
        Collections.reverse(list); 
        outCollection(list); 
    } 
}

 

Comparator接口排序

//要排序的元素对象  
public class Person { 
    private int age; 
    private String name; 
    public Person(int age, String name) { 
        this.age = age; 
        this.name = name; 
    } 
    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 "Person{" + 
                "age=" + age + 
                ", name='" + name + '\'' + 
                '}'; 
    } 
 

 

import java.util.Comparator; 
//Person类的排序接口 
public class PersonComparator implements 
Comparator<Person> { 
       public int compare(Person o1, Person o2) { 
        return o1.getAge() - o2.getAge(); 
    } 
}
import java.util.*; 
/* 结论:排序针对的是确切的集合对象,当集合对象的元素发生变化时,集合内的元素不会自动重新排序. */ 
public class TestComparator { 
    public static String outCollection(Collection coll) { 
        StringBuffer sb = new StringBuffer(); 
        for (Object obj : coll) { 
            sb.append(obj + "\n"); 
        } 
        System.out.println(sb.toString()); 
        return sb.toString(); 
    } 
    public static void main(String args[]) {  test1(); } 
    public static void test1() { 
        System.out.println("----------test1()---------"); 
        System.out.println("升序排序测试:"); 
        List<Person> listPerson = new ArrayList<Person>(); 
        Person person1 = new Person(34, "lavasoft"); 
        Person person2 = new Person(12, "lavasoft"); 
        Person person3 = new Person(23, "leizhimin"); 
        Person person4 = new Person(13, "sdg"); 
        listPerson.add(person1); 
        listPerson.add(person2); 
        listPerson.add(person3); 
        Comparator<Person> ascComparator = new PersonComparator(); 
     //利用Collections静态工具方法对List进行排序 
        Collections.sort(listPerson, ascComparator); 
        outCollection(listPerson); 
     System.out.println("继续添加一个Person对象:"); 
        listPerson.add(person4); 
        outCollection(listPerson); 
        System.out.println("添加一个对象后,重新排序:"); 
        Collections.sort(listPerson, ascComparator); 
        outCollection(listPerson); 
        System.out.println("\n降序排序测试:"); 
        Comparator<Person> descComparator = Collections.reverseOrder(ascComparator); 
        System.out.println("利用反转后的排序接口对象:"); 
        Collections.sort(listPerson, descComparator); 
        outCollection(listPerson); 
        System.out.println("\n求最大最小元素测试:"); 
        Person p_max = Collections.max(listPerson, ascComparator); 
        Person p_min = Collections.min(listPerson, ascComparator); 
        System.out.println("最大元素为:" + p_max.toString()); 
        System.out.println("最小元素为:" + p_min.toString()); 
    } 
}

 
   集合Map排序

Map<String, Integer> map = new TreeMap<String, Integer>();    
map.put("j2se", 20);    
map.put("j2ee", 10);    
map.put("j2me", 30);    
List<Map.Entry<String, Integer>> infoIds = new ArrayList<Map.Entry<String, Integer>>( map.entrySet());    
//排序前    
for (int i = 0; i < infoIds.size(); i++) {    
String id = infoIds.get(i).toString();    
System.out.println(id);    
}    
//排序    
Collections.sort(infoIds, new Comparator<Map.Entry<String, Integer>>() {    
public int compare(Map.Entry<String, Integer> o1,Map.Entry<String, Integer> o2) {    
return (o2.getValue() - o1.getValue());    
} });    
//排序后    
for (int i = 0; i < infoIds.size(); i++) {    
String id = infoIds.get(i).toString();    
System.out.println(id);    
}   
排序前:    
j2ee=10    
j2me=30    
j2se=20    
排序后:    
j2me=30    
j2se=20    
j2ee=10

 

 6.    javahashcode()equals()

equals()hashcode()这两个方法都是从object类中继承过来的。String Math、还有IntegerDouble等都覆盖了equalshashcode方法

equals()方法在object类中定义如下:默认是按地址值进行的比较(即对象的引用)
public boolean equals(Object obj) { return (this == obj); }

hashcode默认是对象的地址,由于在内存中的地址肯定是不同的,所以运算得到的hashcode一般不会相同。

hashCode的作用: hashCode()是用来产生哈希玛的,而哈希玛是用来在散列存储结构中确定对象的存储地址的。HashSet来说,在将对象存入其中时,通过被存入对象的 hashCode() 来确定对象在 HashSet 中的存储地址,通过equals()来确定存入的对象是否重复,hashCode() equals()都需要自己重新定义。

equals()相等的两个对象,hashcode()一定相等;

hashcode()相等,equals()可能相等,也可能不等

   

public class HashSetTest {
	public static void main(String[] args) {
		HashSet<Student> hs = new HashSet<Student>();
		hs.add(new Student(1, "zhangsan"));
		hs.add(new Student(2, "lisi"));
		hs.add(new Student(3, "wangwu"));
		hs.add(new Student(1, "zhangsan"));  
		Iterator<Student> it = hs.iterator();
		while (it.hasNext()) {
			System.out.println(it.next());
		}
	}
}
class Student {
	int num;
	String name;
	Student(int num, String name) {
		this.num = num;
		this.name = name;
	}
	public int hashCode() {
		return num*name.hashCode();
	}
	public boolean equals(Object o) {
		Student s = (Student) o;
		return num == s.num && name.equals(s.name);
	}
	public String toString() {
		return num + ":" + name;
	} 
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值