Collection中List和Set

List

List:有序,可重复,有索引。 
	|--ArrayList:底层数据结构是数组结构。线程不安全的。所以ArrayList的出现替代了Vector.
				但是查询的速度很快.
	|--Vector:底层数据结构是数组结构。jdk1.0版本。线程安全的。无论增删还是查询都非常慢。
	|--LinkedList:底层是链表数据结构。线程不安全的,同时对元算的增删操作效率很高 

可变长度的数组:
	ArrayList内部封装了一个默认长度为10的数组。
	 当超出长度时,集合内部会自动生成一个新的数组。
	 将原数组中的元素复制到新数组中,在将新元素添加到新数组。
新数组到底多长呢?
	ArrayList 50%延长。
	Vector 100%延长。

为什么ArrayList 和LinkedList具有本身的特点
ArrayList 是连续的,添加的话,就会让数组中元素都去移动一下.
LinkedList链表直接改变链表添加:
如图:

  

 Set集合的特点

/*
Collection
	|--List:有序(存的顺序和取的顺序一致。),元可以重复,元素都有索引。
		|--ArrayList:
		|--LinkedList:
	|--Set:无序,不可以重复元素。Set接口的方法和Collection中的方法一致。
								Set接口取出元素的方法只有迭代器。
		|--HashSet:底层数据结构是哈希表。哈希表这种结构,其实就是对哈希值的存储。
					而且每一个对象都有自己的哈希值。因为Object类中的有一个方法hashCode方法。
					如何保证元素唯一性的呢?
					通过判断元素的hashCode方法,和equals方法完成的。
					当hashCode值相同是,会在判断一次euqals方法的返回只是是否为true。
					如果hashCode值不相同,就确定元素的哈希表中的位置,就不用在判断equals了。
					当哈希表中有一个桶结构。每一个桶都有一个哈希值,当哈希值相同,但是equals为false是,
					这些元素都存放一个桶里。
		|--TreeSet:可以对Set集合中的元素进行排序。
					数据结构是二叉树数据结构。这种结构,可以提高排序性能。
					它又是如何保证元素唯一性的呢?
					是根据比较方法的返回值确定的。只要返回的是0.就代表元素重复。


import java.util.*;

/*
HashSet集合是如何保证元素唯一性的?

HashSet集合保证元素唯一性,依赖的是元素的hashCode方法和euqals方法。
当元素的哈希值不同时,元素都有自己的独立位置。不需要在判断元素的equals方法,
当元素的哈希值相同时,这时元素在哈希表中位置相同,这时就需要在判断一次元素的内容是否相同。
就需要调用元素的equals方法进行一次比较。如果equals返回是true。那么视为两个元素为重复元素。
只储存一个。
如果返回是false,那么这两个元素不是重复元素,会存储在同一个哈希值上。

为了建立自定义对象判断元素是否重复的依据。
需要覆盖hashCode方法,和equals方法。
而且最好依据对象的特有条件来建立hashcode和euqals的实现。


*/
class HashSetDemo2 
{
	public static void main(String[] args) 
	{
		//往HashSet集合中存储自定义对象。
		HashSet hs = new HashSet();
		hs.add(new Person("lisi1",21));
		hs.add(new Person("lisi4",24));
		hs.add(new Person("lisi2",22));
		hs.add(new Person("lisi4",24));
		hs.add(new Person("lisi7",27));
		System.out.println("--------");
		Iterator it = hs.iterator();
		while(it.hasNext())
		{
			Person p = (Person)it.next();

			System.out.println(p.getName()+"....."+p.getAge()+"....."+p.hashCode());
		}
		/**/
	}
}

//人对象,如果姓名,年龄相同视为同一个对象。就不进行存储了。

class Person
{
	private String name;
	private int age;
	Person(String name,int age)
	{
		this.name = name;
		this.age = age;
	}
	
	public int hashCode()
	{
		System.out.println(this+"......hashCode");

		final int NUMBER = 38;
		return name.hashCode()+age*NUMBER;
		//return 1;
	}
	/**/
	public boolean equals(Object obj)
	{	
		//System.out.println(this+"....equals...."+obj);
		
		if(this==obj)
			return true;

		if(!(obj instanceof Person))
			return false;
		Person p = (Person)obj;

		return this.name.equals(p.name) && this.age==p.age;
		/**/
		//return true;

	}
	public String getName()
	{
		return name;
	}
	public int getAge()
	{
		return age;
	}
	public String toString()
	{
		return name+"::"+age;
	}
}
			
		
		
import java.util.*;

/*
当treeset集合中存储的元素不具备比较功能。
或者具备的比较功能不是所需要的。
例如:Person对象中的自然排序是按照年龄排序。
但是现在需求是想安装姓名排序。该源代码这种方式想都不要想。有这种想法就是犯罪。

该如何解决这个问题?
既然元素具备的比较方式不满足应用。
这时,可以让集合自身具备比较性。
需要集合一初始化就具备比较功能。因为要在添加元素前具备。
就需要在构造函数进行初始化。

只要将一个实现了Comparator接口的子类对象作为参数传递给TreeSet集合的构造函数即可。
这样该集合就具备了比较功能。

建议使用第二种排序方式。

总结:
TreeSet排序方式有两种。
1,让元素自身具备比较性。
	其实是让元素实现Comparable接口,覆盖compareTo方法。
	这称为元素的自然排序。

2,当元素自身不具备比较性,或者元素具备的比较性不是所需要的,
	可以让集合自身具备比较性。
	定义一个比较器:
	其实就是定义一个类,实现Comparator接口。覆盖compare方法。
	将Comparator接口的子类对象作为参数传递给TreeSet的构造函数。


	当元素自身具备比较性,同时TreeSet集合也具备比较器,
	这时以比较器为主.



到了这里,
一般在描述一个对象时,如果该对象封装了具体的数据,会出现很多这样的对象比如:员工,学生对象等.
这时就需要进行容器的存储.

那么描述该类对象时,
一定要复写几个方法.
1,hashCode()
2,equals()
3,toString()
4,最好实现Comparable接口让该类具备自然排序功能。

建立对象自身判断是否相同的依据,同时让对象具备基本的比较性。




*/

class TreeSetDemo3 
{
	public static void main(String[] args) 
	{
		TreeSet ts = new TreeSet(new CompareByName());

		ts.add(new Person("lisi1",21));
		ts.add(new Person("lisi4",29));
		ts.add(new Person("lisi2",67));
		ts.add(new Person("lisi8",28));
		ts.add(new Person("lisi0",20));

		System.out.println(ts);
	}
}
//自定义一个比较器。
class CompareByName implements Comparator
{
	public int compare(Object o1,Object o2)
	{
		Person p1 = (Person)o1;
		Person p2 = (Person)o2;

		int num = p1.getName().compareTo(p2.getName());

		return num==0?p1.getAge()-p2.getAge():num;

	}
}

class Person implements Comparable
{
	private String name;
	private int age;
	Person(String name,int age)
	{
		this.name = name;
		this.age = age;
	}

	//人的自然排序是按照年龄排序
	public int compareTo(Object obj)
	{
		Person p = (Person)obj;

		int num = new Integer(this.age).compareTo(new Integer(p.age));

		return num==0?this.name.compareTo(p.name):num;

	}
	public String getName()
	{
		return name;
	}
	public int getAge()
	{
		return age;
	}
	public String toString()
	{
		return name+"::"+age;
	}
}

  

原文地址:https://www.cnblogs.com/liushisaonian/p/8598426.html