Collection接口表示一组对象,这些对象也成为Collection的元素。一些Collection接口允许有重复元素,而另一些则不允许。一些Collection接口是有序的,而另一些则是无序的。
重复:两个对象通过equals判断相等。(equals子类对象可以复写)
有序:元素存入的顺序和取出的顺序相同。
set接口存放的元素是无序的且不包含重复元素。List接口存放的元素是有序的并且是允许重复的。
import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Set; import java.util.TreeSet; import java.util.concurrent.atomic.AtomicInteger; /** * 实现Set接口的容器存储对象时,根据每个对象的哈希码值(调用hashCode方法获得)用固定的算法算出它的存储索引, * 把对象存放在一个叫散列表的相应位置中;如果该位置没有其他元素,就只需直接存入。如果该位置已经有其他元素, * 就会将新元素与该位置的【所有】对象进行比较(调用equals),以查看该容器中是否已经存入该对象,如果不存在该对象, * 就存放该对象,若已经存在则直接使用该【存在】的对象。 * @author wanghl * * 【Set元素不能重复】 * 【List元素可重复】 * *【hasCode散列介绍:】 *如果一个容器有100个元素,在进行添加一个元素时,由于需要判断是否重复,那么需要进行100次equals方法。如果每增加一个元素, *就需要多执行一次equals,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了,这样效率就大大降低。于是,java *采用了哈希表的原理。哈希算法也成为散列算法,是将数据依据特定的算法直接指定到一个地址上(我们暂且将hasCode值当做对象存储的物理 *地址的一个索引,暂时不要关心算法计算)。那么,添加新元素时,先通过hasCode索引查看这个位置是否已经存入对象,如果不存在,则直接将 *新元素存放在这个位置,不需要再调用equals方法。如果已经存在对象,则在调用equals方法进行比较,相同就不存,直接使用存在元素,不同的话 *就散列其他地址。这样就使equals方法调用的次数大大降低。 *【两个对象相同,那么他们的hasCode一定相同,hasCode相同,两个对象不一定相同】 *【存入到Set集合的对象,不一定会调用equals方法】 */ public class SetTest { public static void main(String args[]){ /** * HashSet是Set接口实现类之一,使用哈希码值进行存放,所以也能够快速查找。 * 【HashSet不保存加入容器的元素的顺序】 */ HashSet<Persion1> set1 = new HashSet<Persion1>(); System.out.println("------------------------hasCode与equals对Set接口实现类的影响"); /** * 打印结果为: * p--->12Persion1@01 * p--->12Persion1@02 * Set count is:1 * Persion1 对象为:12Persion1@01 * 【验证:】set接口,如果两个元素的hasCode相等,equals相等,则说明对象存在,直接使用该存在对象,不进行【覆盖】。 */ Persion1 pa1 = new Persion1(12); Persion1 pa2 = new Persion1(12); System.out.println("p--->"+pa1); System.out.println("p--->"+pa2); set1.add(pa1); set1.add(pa2); System.out.println("Set count is:"+set1.size()); for(Persion1 p :set1){ System.out.println("Persion1 对象为:"+p); } System.out.println("---------------------------------------"); //------------------------------------------- /** * 【注意:】Persion1与Persion2,仅仅在equals方法判断的地方存在差异。 * 【打印:】 * p--->12Persion2@01 * p--->12Persion2@02 * Set count is:2 * Persion2 对象为:12Persion2@02 * Persion2 对象为:12Persion2@01 * 【说明:】 * 下面的 这两个对象存放在同一个hasCode所算出的索引上,由于equals不同,故而可存。 */ HashSet<Persion2> set2 = new HashSet<Persion2>(); Persion2 pb1 = new Persion2(12); Persion2 pb2 = new Persion2(12); System.out.println("p--->"+pb1); System.out.println("p--->"+pb2); set2.add(pb1); set2.add(pb2); System.out.println("Set count is:"+set2.size()); for(Persion2 p :set2){ System.out.println("Persion2 对象为:"+p); } System.out.println("---------------------------------------"); //------------------------------------------- /** * 输出是无须的。 * 【打印:】 * p ---->44Persion1@06 * p ---->33Persion1@05 * p ---->22Persion1@04 * p ---->11Persion1@03 * p ---->better * p ---->best * p ---->good */ HashSet set3 = new HashSet(); Persion1 pc1 = new Persion1(11); Persion1 pc2 = new Persion1(22); Persion1 pc3 = new Persion1(33); Persion1 pc4 = new Persion1(44); set3.add(pc1); set3.add(pc2); set3.add(pc3); set3.add(pc4); set3.add("good"); set3.add("better"); set3.add("best"); Iterator<Persion1> iterator = set3.iterator(); while(iterator.hasNext()){ Object p = iterator.next(); System.out.println("p ---->"+p+",hasCode is:"+p.hashCode()); } System.out.println("*********************************************"); //------------------------------------------- /** * LinkedHashSet 根据哈希码进行存放,同时用链表记录元素的加入顺序。 * 通过链表存储对象,一般插入和删除效率较高,检索效率较低。 */ LinkedHashSet linkedSet = new LinkedHashSet(); /** * LinkedHashSet记录元素加入顺序 * 打印: * p ***> is:55Persion1@07,hasCode is:0 * p ***> is:66Persion1@08,hasCode is:0 * p ***> is:77Persion1@09,hasCode is:0 * p ***> is:88Persion1@010,hasCode is:0 * p ***> is:aaaa,hasCode is:2986048 * p ***> is:bbbb,hasCode is:3016832 * p ***> is:cccc,hasCode is:3047616 */ Persion1 pd1 = new Persion1(55); Persion1 pd2 = new Persion1(66); Persion1 pd3 = new Persion1(77); Persion1 pd4 = new Persion1(88); linkedSet.add(pd1); linkedSet.add(pd2); linkedSet.add(pd3); linkedSet.add(pd4); linkedSet.add("aaaa"); linkedSet.add("bbbb"); linkedSet.add("cccc"); for(Object p:linkedSet){ System.out.println("p ***> is:"+p+",hasCode is:"+p.hashCode()); } System.out.println("---------------------------------------"); //------------------------------------------- /** * 有多个不同类型的对象加入TreeSet,就会报异常。 * 对于自定义的类,它的对象只能存放一个,而且实现类不需要实现【Comparable接口】。 * 但是,如果 想要存放多个自定义的类的对象, * 不实现Comparable接口就会发生java.lang.ClassCastException异常 。 */ Set treeSet = new TreeSet(); Persion1 pe1 = new Persion1(12); treeSet.add(pe1); /*treeSet.add(new String("hello"));*/ Iterator itor = treeSet.iterator(); while(itor.hasNext()){ System.out.println("TreeSet p is:"+itor.next()); } System.out.println("---------------------------------------"); //------------------------------------------- /** * Set排序 * Persion3实现了排序的接口Comparable * p ***> is:0Persion3@07,hasCode is:0 * p ***> is:1Persion3@01,hasCode is:0 * p ***> is:2Persion3@03,hasCode is:0 * p ***> is:4Persion3@06,hasCode is:0 * p ***> is:5Persion3@04,hasCode is:0 * p ***> is:8Persion3@02,hasCode is:0 * p ***> is:9Persion3@05,hasCode is:0 * 按照Age进行排序 */ Set<Persion3> sortSet = new TreeSet<Persion3>(); Persion3 pf1 = new Persion3(1); Persion3 pf2 = new Persion3(8); Persion3 pf3 = new Persion3(2); Persion3 pf4 = new Persion3(5); Persion3 pf5 = new Persion3(9); Persion3 pf6 = new Persion3(4); Persion3 pf7 = new Persion3(0); sortSet.add(pf1); sortSet.add(pf2); sortSet.add(pf3); sortSet.add(pf4); sortSet.add(pf5); sortSet.add(pf6); sortSet.add(pf7); for(Persion3 p:sortSet){ System.out.println("p ***> is:"+p+",hasCode is:"+p.hashCode()); } System.out.println("---------------------------------------"); /** * Set排序,按照【排序器】进行排序Comparetor * 打印: * p ***> is:1Persion3@01,hasCode is:0 * p ***> is:8Persion3@02,hasCode is:0 * p ***> is:2Persion3@03,hasCode is:0 * p ***> is:5Persion3@04,hasCode is:0 * p ***> is:9Persion3@05,hasCode is:0 * p ***> is:4Persion3@06,hasCode is:0 * p ***> is:0Persion3@07,hasCode is:0 * 按照index进行排序 */ TreeSet<Persion3> sortSetByComparator = new TreeSet<Persion3>(new ComparetorByIndex()); sortSetByComparator.add(pf1); sortSetByComparator.add(pf2); sortSetByComparator.add(pf3); sortSetByComparator.add(pf4); sortSetByComparator.add(pf5); sortSetByComparator.add(pf6); sortSetByComparator.add(pf7); for(Persion3 p:sortSetByComparator){ System.out.println("p ***> is:"+p+",hasCode is:"+p.hashCode()); } System.out.println("---------------------------------------"); } } class Persion1{ public int mAge; private static AtomicInteger atIndex = new AtomicInteger();//原子类型 public int index; public Persion1(int age){ mAge = age; index = atIndex.addAndGet(1); } @Override public int hashCode() { return 0; } @Override public String toString() { return mAge+""+super.toString()+index; } @Override public boolean equals(Object arg0) { if(arg0 instanceof Persion1){ Persion1 p = (Persion1)arg0; return mAge == p.mAge; } return super.equals(arg0); } } class Persion2{ public int mAge; private static AtomicInteger atIndex = new AtomicInteger();//原子类型 public int index; public Persion2(int age){ mAge = age; index = atIndex.addAndGet(1); } @Override public int hashCode() { return 0; } @Override public String toString() { return mAge+""+super.toString()+index; } @Override public boolean equals(Object arg0) { if(arg0 instanceof Persion2){ Persion2 p = (Persion2)arg0; return mAge != p.mAge; } return super.equals(arg0); } } class Persion3 implements Comparable<Persion3>{ public int mAge; private static AtomicInteger atIndex = new AtomicInteger();//原子类型 public int index; public Persion3(int age){ mAge = age; index = atIndex.addAndGet(1); } @Override public int hashCode() { return 0; } @Override public String toString() { return mAge+""+super.toString()+index; } @Override public boolean equals(Object arg0) { if(arg0 instanceof Persion3){ Persion3 p = (Persion3)arg0; return mAge != p.mAge; } return super.equals(arg0); } @Override public int compareTo(Persion3 p) { return mAge - p.mAge ; } } class ComparetorByAge implements Comparator<Persion3>{ @Override public int compare(Persion3 p0, Persion3 p1) { return p0.mAge - p1.mAge; } } class ComparetorByIndex implements Comparator<Persion3>{ @Override public int compare(Persion3 p0, Persion3 p1) { return p0.index - p1.index; } }
Collection接口表示一组对象,这些对象也成为Collection的元素。一些Collection接口允许有重复元素,而另一些则不允许。一些Collection接口是有序的,而另一些则是无序的。
重复:两个对象通过equals判断相等。(equals子类对象可以复写)
有序:元素存入的顺序和取出的顺序相同。
set接口存放的元素是无序的且不包含重复元素。List接口存放的元素是有序的并且是允许重复的。
import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashSet; import java.util.Set; import java.util.TreeSet; import java.util.concurrent.atomic.AtomicInteger; /** * 实现Set接口的容器存储对象时,根据每个对象的哈希码值(调用hashCode方法获得)用固定的算法算出它的存储索引, * 把对象存放在一个叫散列表的相应位置中;如果该位置没有其他元素,就只需直接存入。如果该位置已经有其他元素, * 就会将新元素与该位置的【所有】对象进行比较(调用equals),以查看该容器中是否已经存入该对象,如果不存在该对象, * 就存放该对象,若已经存在则直接使用该【存在】的对象。 * @author wanghl * * 【Set元素不能重复】 * 【List元素可重复】 * *【hasCode散列介绍:】 *如果一个容器有100个元素,在进行添加一个元素时,由于需要判断是否重复,那么需要进行100次equals方法。如果每增加一个元素, *就需要多执行一次equals,那么当元素很多时,后添加到集合中的元素比较的次数就非常多了,这样效率就大大降低。于是,java *采用了哈希表的原理。哈希算法也成为散列算法,是将数据依据特定的算法直接指定到一个地址上(我们暂且将hasCode值当做对象存储的物理 *地址的一个索引,暂时不要关心算法计算)。那么,添加新元素时,先通过hasCode索引查看这个位置是否已经存入对象,如果不存在,则直接将 *新元素存放在这个位置,不需要再调用equals方法。如果已经存在对象,则在调用equals方法进行比较,相同就不存,直接使用存在元素,不同的话 *就散列其他地址。这样就使equals方法调用的次数大大降低。 *【两个对象相同,那么他们的hasCode一定相同,hasCode相同,两个对象不一定相同】 *【存入到Set集合的对象,不一定会调用equals方法】 */ public class SetTest { public static void main(String args[]){ /** * HashSet是Set接口实现类之一,使用哈希码值进行存放,所以也能够快速查找。 * 【HashSet不保存加入容器的元素的顺序】 */ HashSet<Persion1> set1 = new HashSet<Persion1>(); System.out.println("------------------------hasCode与equals对Set接口实现类的影响"); /** * 打印结果为: * p--->12Persion1@01 * p--->12Persion1@02 * Set count is:1 * Persion1 对象为:12Persion1@01 * 【验证:】set接口,如果两个元素的hasCode相等,equals相等,则说明对象存在,直接使用该存在对象,不进行【覆盖】。 */ Persion1 pa1 = new Persion1(12); Persion1 pa2 = new Persion1(12); System.out.println("p--->"+pa1); System.out.println("p--->"+pa2); set1.add(pa1); set1.add(pa2); System.out.println("Set count is:"+set1.size()); for(Persion1 p :set1){ System.out.println("Persion1 对象为:"+p); } System.out.println("---------------------------------------"); //------------------------------------------- /** * 【注意:】Persion1与Persion2,仅仅在equals方法判断的地方存在差异。 * 【打印:】 * p--->12Persion2@01 * p--->12Persion2@02 * Set count is:2 * Persion2 对象为:12Persion2@02 * Persion2 对象为:12Persion2@01 * 【说明:】 * 下面的 这两个对象存放在同一个hasCode所算出的索引上,由于equals不同,故而可存。 */ HashSet<Persion2> set2 = new HashSet<Persion2>(); Persion2 pb1 = new Persion2(12); Persion2 pb2 = new Persion2(12); System.out.println("p--->"+pb1); System.out.println("p--->"+pb2); set2.add(pb1); set2.add(pb2); System.out.println("Set count is:"+set2.size()); for(Persion2 p :set2){ System.out.println("Persion2 对象为:"+p); } System.out.println("---------------------------------------"); //------------------------------------------- /** * 输出是无须的。 * 【打印:】 * p ---->44Persion1@06 * p ---->33Persion1@05 * p ---->22Persion1@04 * p ---->11Persion1@03 * p ---->better * p ---->best * p ---->good */ HashSet set3 = new HashSet(); Persion1 pc1 = new Persion1(11); Persion1 pc2 = new Persion1(22); Persion1 pc3 = new Persion1(33); Persion1 pc4 = new Persion1(44); set3.add(pc1); set3.add(pc2); set3.add(pc3); set3.add(pc4); set3.add("good"); set3.add("better"); set3.add("best"); Iterator<Persion1> iterator = set3.iterator(); while(iterator.hasNext()){ Object p = iterator.next(); System.out.println("p ---->"+p+",hasCode is:"+p.hashCode()); } System.out.println("*********************************************"); //------------------------------------------- /** * LinkedHashSet 根据哈希码进行存放,同时用链表记录元素的加入顺序。 * 通过链表存储对象,一般插入和删除效率较高,检索效率较低。 */ LinkedHashSet linkedSet = new LinkedHashSet(); /** * LinkedHashSet记录元素加入顺序 * */ Persion1 pd1 = new Persion1(55); Persion1 pd2 = new Persion1(66); Persion1 pd3 = new Persion1(77); Persion1 pd4 = new Persion1(88); linkedSet.add(pd1); linkedSet.add(pd2); linkedSet.add(pd3); linkedSet.add(pd4); linkedSet.add("aaaa"); linkedSet.add("bbbb"); linkedSet.add("cccc"); for(Object p:linkedSet){ System.out.println("p ***> is:"+p+",hasCode is:"+p.hashCode()); } System.out.println("---------------------------------------"); //------------------------------------------- /** * 有多个不同类型的对象加入TreeSet,就会报异常。 * 对于自定义的类,它的对象只能存放一个,而且实现类不需要实现【Comparable接口】。 * 但是,如果 想要存放多个自定义的类的对象, * 不实现Comparable接口就会发生java.lang.ClassCastException异常 。 */ Set treeSet = new TreeSet(); Persion1 pe1 = new Persion1(12); treeSet.add(pe1); /*treeSet.add(new String("hello"));*/ Iterator itor = treeSet.iterator(); while(itor.hasNext()){ System.out.println("TreeSet p is:"+itor.next()); } System.out.println("---------------------------------------"); //------------------------------------------- /** * Set排序 * Persion3实现了排序的接口Comparable */ Set<Persion3> sortSet = new TreeSet<Persion3>(); Persion3 pf1 = new Persion3(1); Persion3 pf2 = new Persion3(8); Persion3 pf3 = new Persion3(2); Persion3 pf4 = new Persion3(5); Persion3 pf5 = new Persion3(9); Persion3 pf6 = new Persion3(4); Persion3 pf7 = new Persion3(0); sortSet.add(pf1); sortSet.add(pf2); sortSet.add(pf3); sortSet.add(pf4); sortSet.add(pf5); sortSet.add(pf6); sortSet.add(pf7); for(Persion3 p:sortSet){ System.out.println("p ***> is:"+p+",hasCode is:"+p.hashCode()); } System.out.println("---------------------------------------"); /** * Set排序,按照【排序器】进行排序Comparetor */ TreeSet<Persion3> sortSetByComparator = new TreeSet<Persion3>(new ComparetorByIndex()); sortSetByComparator.add(pf1); sortSetByComparator.add(pf2); sortSetByComparator.add(pf3); sortSetByComparator.add(pf4); sortSetByComparator.add(pf5); sortSetByComparator.add(pf6); sortSetByComparator.add(pf7); for(Persion3 p:sortSetByComparator){ System.out.println("p ***> is:"+p+",hasCode is:"+p.hashCode()); } System.out.println("---------------------------------------"); } } class Persion1{ public int mAge; private static AtomicInteger atIndex = new AtomicInteger();//原子类型 public int index; public Persion1(int age){ mAge = age; index = atIndex.addAndGet(1); } @Override public int hashCode() { return 0; } @Override public String toString() { return mAge+""+super.toString()+index; } @Override public boolean equals(Object arg0) { if(arg0 instanceof Persion1){ Persion1 p = (Persion1)arg0; return mAge == p.mAge; } return super.equals(arg0); } } class Persion2{ public int mAge; private static AtomicInteger atIndex = new AtomicInteger();//原子类型 public int index; public Persion2(int age){ mAge = age; index = atIndex.addAndGet(1); } @Override public int hashCode() { return 0; } @Override public String toString() { return mAge+""+super.toString()+index; } @Override public boolean equals(Object arg0) { if(arg0 instanceof Persion2){ Persion2 p = (Persion2)arg0; return mAge != p.mAge; } return super.equals(arg0); } } class Persion3 implements Comparable<Persion3>{ public int mAge; private static AtomicInteger atIndex = new AtomicInteger();//原子类型 public int index; public Persion3(int age){ mAge = age; index = atIndex.addAndGet(1); } @Override public int hashCode() { return 0; } @Override public String toString() { return mAge+""+super.toString()+index; } @Override public boolean equals(Object arg0) { if(arg0 instanceof Persion3){ Persion3 p = (Persion3)arg0; return mAge != p.mAge; } return super.equals(arg0); } @Override public int compareTo(Persion3 p) { return mAge - p.mAge ; } } class ComparetorByAge implements Comparator<Persion3>{ @Override public int compare(Persion3 p0, Persion3 p1) { return p0.mAge - p1.mAge; } } class ComparetorByIndex implements Comparator<Persion3>{ @Override public int compare(Persion3 p0, Persion3 p1) { return p0.index - p1.index; } }