集合框架

集合框架接口和类很多,这里总结下常用的几个类和接口,以及一些常用的方法


图片

图1 集合框架继承关系图
注:本文的讲解顺序为图中的标号顺序。


一、接口

Collection接口

作为集合框架的根接口其方法大致可以分为七大类:
1.增(add)
     boolean add(E e)  
     boolean addAll(Collection<? extends E> c)  
     
2.删除remove
     void clear()
     boolean remove(Object o)  
     boolean removeAll(Collection<?> c)  
     
3.查询
     boolean contains(Object o)  
      boolean containsAll(Collection<?> c)  
       boolean retainAll(Collection<?> c)  
       
4.遍历
     Iterator<E> iterator()
 注:编辑集合框架元素的三大方法:
  1.普通for循环
  2.foreach
  3.迭代器iterator

     
5.属性
     boolean isEmpty()
      int size()
 6.定义自己的equals原则
      boolean equals(Object o)
     int hashCode()
 7.转化为数组
      Object[] toArray()  
     <T> T[] toArray(T[] a)
 注:
 ①Collection的所有实现类都重写了toString()方法,所以输出对象是会按照一定模式输出
 ②Collection集合中添加元素时均被接受为Object类型

List接口

1.有序:
    List底层数据操作集合是数组(可参见源码)
2.可重复性
//实例程序:
package com.heima.collection;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.junit.Test;

public class ListTest {

    @Test
    public void testIterator() {
        List<Object> list=new ArrayList<Object>();
        
        list.add(123);
        list.add(456);
        list.add("abc");
        list.add("tcl");
//        遍历方法一
        Iterator iterator=list.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
//        遍历方法二
        for(Object o:list){
            System.out.println(o);
        }
//        遍历方法三
        for(int i=0;i<list.size();i++){
            System.out.println(list.get(i));
        }
        
        
    }

}

HashSet接口

1.无序性!=随机性
    元素每次存储的位置都是按照哈希算法来获取的。看似无序,但是是有一定规律的。所以每次需要重写插入类对象的hashCode()方法
 @Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result
				+ ((birthday == null) ? 0 : birthday.hashCode());
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}


2.不可重复性
    即每次插入的元素不可以相同。这里需要重写从Object类中继承过来的方法equals(),定义自己的相等标准。

 @Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Employee other = (Employee) obj;
		if (age != other.age)
			return false;
		if (birthday == null) {
			if (other.birthday != null)
				return false;
		} else if (!birthday.equals(other.birthday))
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
    

实例:
// 实例程序:
 
 /**
	 * 无序性:根据hashCode函数获得存储位置
	 * 不可重复性:重写javaBean的hashcode同且equals
	 */
	@Test
	public void testHashSet() {
		Set<Object> set = new HashSet<Object>();

		set.add(null);
		set.add(123);
		set.add("abc");
		set.add(new Person("bb", 12));
		set.add(new Person("bb", 12));

		Iterator<Object> iterator = set.iterator();
		while (iterator.hasNext()) {
			System.out.println(iterator.next());
		}
	}
    
    
    
//Person.java
package com.heima.collection;

public class Person  implements Comparable<Object>{

	private String name;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	/*@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}*/
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Person other = (Person) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	public int compareTo(Object o) {
		if(o instanceof Person){
				int i= ((Person) o).getAge()-this.age;
				if(i==0){
					return ((Person) o).getName().compareTo(this.name);
				}
				return i;
		}
		return 0;
	}

综上所述,为了遵守Set的两大特性:如果要往Set中加入元素,那么要重写此元素的hashCode()和equals()方法。因为在集合调用其add方法时,会首先根据hashCode判断插入位置是否相同,然后判断equals是否为true。此时重写的结果有四种可能
1.如果同为false,那么则可以顺利插入
2.hashCode为true,equals为false,那么此时会在hash表的某一个位置形成一个链式结构。
3.hashCode为false,equals为true,那么此时会在hash表的两个位置插入两个相同的对象。
4.hashCode为true,equals为true,那么此时不会进入哈希表。

显然,第2、3两种情况是很奇诡的,所以要求重写的hashCode()和equals()方法的结果应该保持一致。

LinkedHashSet

特点:可以根据插入时的顺序对所有元素进行遍历。




TreeSet


TreeSet在原本Set的基础上还加上了一些特性:
1.TreeSet中要求添加的元素为同一个类的实例
2.定义自己的排序规则:
①定制排序:加入到TreeSet中的类的实例需要先生成Comparator接口并且实现compare()方法,使得元素按照自己的预期排序。
@Test
	public void testTreeSetCompare() {
		Set set = new TreeSet(new Comparator() {

			public int compare(Object o1, Object o2) {
				if (o1 instanceof Person && o2 instanceof Person) {
					int i = ((Person) o1).getAge() - ((Person) o2).getAge();
					if (i == 0) {
						return ((Person) o1).getName().compareTo(
								((Person) o2).getName());
					}
					return i;
				}
				return 0;
			}
		});

		 set.add(null);
		 set.add(123);
		 set.add("abc");
		set.add(new Person("bb", 12));
		set.add(new Person("bb", 13));

		Iterator<Object> iterator = set.iterator();
		while (iterator.hasNext()) {
			System.out.println(iterator.next());
		}
	}

②自然排序:加入到TreeSet中的类的实例需要实现Comparable接口并且实现compareTo()方法,使得元素按照自己的预期排序
package com.heima.collection;

public class Person  implements Comparable<Object>{

	private String name;
	private int age;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	/*@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}*/
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Person other = (Person) obj;
		if (age != other.age)
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}
	public Person(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	public int compareTo(Object o) {
		if(o instanceof Person){
				int i= ((Person) o).getAge()-this.age;
				if(i==0){
					return ((Person) o).getName().compareTo(this.name);
				}
				return i;
		}
		return 0;
	}
	
	
	
	
	
}

@Test
	public void testTreeSet() {
		Set set = new TreeSet();

		// set.add(123);//ClassCastException
		set.add(new Person("bb", 12));
		set.add(new Person("bb", 12));

		Iterator<Object> iterator = set.iterator();
		while (iterator.hasNext()) {
			System.out.println(iterator.next());
		}
	}

只有满足了上面两个条件的之后才能被添加如TreeSet中。

注:添加元素时判断顺序:
①定制排序:compare->hashCode()->equals(),结果务必保持一致!
②自然排序:compareTo->hashCode()->equals(),结果务必保持一致!
推理过程和HashSet一致。

HashMap

①Map接口可以看出是以Set为索引的List,即key为Set,value为类似于List。
②并且对于每一条key-value对又被称作entry纪录。在Map接口中被封装成了Map.Entry

Map接口的方法可以分为:
1.增(add)
     V put(K key, V value)
     void putAll(Map<? extends K,? extends V> m)   
     
2.删除remove
     void clear()
     V remove(Object key)
     
3.查询
     boolean containsKey(Object key)    
      boolean containsValue(Object value)    
     V get(Object key)    
       
4.遍历
    Set<Map.Entry<K,V>> entrySet()  
     Collection<V> values()
      Set<K> keySet()  
     
5.属性
     boolean isEmpty()
      int size()
 6.定义自己的equals原则
      boolean equals(Object o)
     int hashCode()
其余部分均可参见Set

Properties类:key和value均为String类型。

Collectios类:主要是对集合的元素进行操作比如排序Collections.sort(...),最为重要的是因为集合框架中比较常用的一些类:ArrayList、HashSet、TreeSet、HashMap、TreeMap等均为线程不安全的,如果要将他们转化为线程安全的,需要使用静态方法synchronizedXxx(),将其进行包装为线程安全 的。


HashMap和Hashtable的区别:HashMap线程不安全,效率较高,可以存放null-null键值对,但是Hashtable线程安全,效率较低,不可以存放null-null键值对




 
 





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值