黑马程序员_集合框架-Collection-Set(四)
-------android培训、java培训、java学习型技术博客、期待与您交流! ----------
集合框架的顶层接口Collection下的子接口Set,和子接口List一样比较重要。
Set
在Set集合中,有以下几个常子类,HashSet、TreeSet、LinkedHashSet.
元素不能重复,无序,Set接口中的方法和collection的方法一样
HashSetHashSet:内部实际结构是哈希表,是不同步的。
哈希表:将对象经过哈希算法计算成该对象的哈希值,并把哈希值存放在哈希表中,其实哈希值就相当于数组中的角标。所以在查找的时候直接根据哈希值查询,速度很快。
哈希表确定元素是否相同
u 判断的是两个元素的哈希值是否相同,如果相同,再判断两个对象的内容是否相同
u 判断哈希值相同,其实判断的是对象的hashcode的方法,判断内容相同,用的是equlas方法
注意:如果哈希值不同,是不用判断equals.
Hahset集合数据是哈希表,所以存储元素的时候,使用的元素的hashcode方法来确定位置,如果位置相同,在通过元素的equals来确定是否相同。也就是通过对象的hashcode和equals方法来完成对象唯一性的,如果对象的hashcode值不同,那么不用判断equals方法,就直接存储到哈希表中,如果对象的hashcode值相同,那么要再次判断对象的equals 方法是否为true,如果为true,视为相同元素,不存,如果为false,那么视为不同元素,就进行存储。
记住:如果元素要存储到hashset集合中,必须覆盖hashcode方法和equals方法,一般情况下,如果定义的类会产生很多对象,比如人,学生,数,通常都需要覆盖equlas,hashcode方法。建立对象判断是否相同的依据。
HashSet的练习:
import java.util.HashSet;
import java.util.Iterator;
import cn.itheima.bean.Person;
public class HashSetTest {
public static void main(String[] args) {
/*
* 往哈希表中存储自定义对象。
* 往哈希表中的存储的自定义对象,必须覆盖hashCode方法,和equals方法。
*
* 我也不知道这个对象到底存储到哪个容器中去,
* 那就将hashCode,equals,toString全都覆盖。
* 不覆盖也从Object类中继承了,那还不如覆盖,创建对象自身的判断相同的依据。
*/
HashSet hs = new HashSet();
hs.add(new Person("lisi8",28));
hs.add(new Person("lisi2",22));
hs.add(new Person("lisi2",22));
hs.add(new Person("lisi3",23));
hs.add(new Person("lisi3",23));
hs.add(new Person("lisi4",24));
Iterator it = hs.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
Person已略.
TreeSetTreeSet:可以对集合中的元素进行排序,是不不同步的,
判断元素唯一性的方式:即使根据比较方法的返回结果是否是0,是0,就是相同的元素,不存,
u Treeset对元素进行排序的方式一:
让元素自身具备比较功能,就需要实现comparable接口,覆盖comparaTo( )方法。如果不要按照对象中具备的自然顺序进行排序,如果对象中不具备自然顺序,怎么办?
u 可以使用treeset集合第二种排序方式二:
让集合自身比较功能,定义一个类实现comparator接口,覆盖compare方法。将该类对象作为参数传递给treeset集合的构造函数。
TreeSet练习:Person已略.
import java.util.Iterator;
import java.util.TreeSet;
import cn.itheima.bean.Person;
public class TreeSetTest {
public static void main(String[] args) {
TreeSet ts = new TreeSet();
ts.add(new Person("lisi8",24));
ts.add(new Person("lisi1",27));//ClassCastException:
ts.add(new Person("lisi0",27));
ts.add(new Person("lisi2",22));
ts.add(new Person("lisi9",20));
ts.add(new Person("lisi1",26));
Iterator it = ts.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
Person已略。
LinkedHashSet
代码:
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
public class LinkedHashSetDemo {
/**
* @param args
*/
public static void main(String[] args) {
/*
* 在Set集合中,其实有一个有序集合。就是HashSet的子类LinkedHashSet.
* 顺便提一下:
* LinkedList中特有的操作方法:
* addFirst()
* addLast();
* jdk1.6以后,变成。
* offerFirst();
* offerLast();
* getFirst():获取元素,但不删除,如果列表为空,抛出异常NoSuchElementException
* getLast();
* jdk1.6以后。
* peekFirst();获取元素,但不删除,如果列表为空,返回null。
* peekLast();
* removeFirst():获取元素,并会删除,如果列表为空,抛出异常NoSuchElementException
* removeLast();
* jdk1.6以后。
* pollFirst():获取元素,并会删除,如果列表为空,返回null。
* pollLast();
*
*/
HashSet hs = new LinkedHashSet();
hs.add("nba");
hs.add("xiix");
hs.add("qqq");
hs.add("hahaha");
Iterator it = hs.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
}
同步与非同步:
明确具体集合对象名称的后缀,如果后缀是List都所属于List体系,通常是非同步的,如果后缀是Set都所属set体系,通常是非同步的;这些体系的其他子类对象,后缀不是所属接口名的,一般都是同步的。如vector
数据结构:
前缀是数据结构,后缀是所属体系。
ArrayList:看到Array,明确是数组结构,查询快。
需要唯一吗?
需要:set
需要制定顺序吗:
需要:TreeSet
不需要:hashset
但是想要一个和存储一直的顺序(有序):linkedhashset
不需要:list
选要频繁增删吗:
需要:linkedlist
不需要:arraylist
如果记录每一个容器的结构和所属体系呢?
看名字!
List
Arraylist
Linkedlist
Set
Hashset
Treeset
后缀名就是该集合所属的体系。
前缀名技术该集合的数据结构。
看到就要想到数组,就要想到查询快,有角标。
看到就要想到链表,就要想到增删快,就要想到的方法。
看到就要想到哈希表,就要想到唯一性,就要想到和
看到就要想到排序,想到二叉树,就要想到和
通常这些常用的是线程不安全的。
泛型Jdk1.5出现的安全机制。解决类型安全问题,只能用于编译时期,提高安全性
1、好处将运行时期的问题classCastExceptoin转到了编译时期。
避免了强制转换的麻烦。
2、什么时候用当操作的引用数据类型不确定的时候,就使用泛型,将要操作的引用数据类型传入即可,其实<>就是一个用于接收具体引用数据类型的参数范围。
在程序中,只要用到了带有<>的类或者接口,就要明确传入的引用数据类型。
泛型技术是给编译器使用的技术,用于编译时期,确保了类型的安全。运行时,会将泛型去掉。生成的class问题中是不带泛型的,这个叫泛型的擦除。为什么擦除呢?因为为了兼容运行的类加载器。
泛型的补偿:下运行时,通过获取元素的类型进行转换动作,不用使用者在强制转换了。
泛型类:什么时候用?当类中的操作的引用数据类型不确定时候,就可以使用泛型类来表示。
当方法静态时,不能访问类上定义的泛型,如果静态方法使用泛型,只能将泛型定义在方法上。写在返回值的前面。
泛型接口:将泛型定义在接口上。
泛型的通配符:?未知类型
泛型的限定:?extends E--------->接收E类型或者E的子类型。
?extends E:接收E类型或者E的子类对象,上限
一般在存储元素的时候都是用上限,因为这样取出都是按照上限类型来运算的,不会出现类型安全隐患。
?super E:接收E类型或者E的父类对象,下限
什么时候用下限呢?通常对集合中的元素进行取出操作时。可以用下限。
-------android培训、java培训java学习型技术博客、期待与您交流! ----------更多详情请查看:http://edu.csdn.net