第一部分:HashSet的使用
/ *
|--Set:元素是无序的(存入和取出的顺去不一定一致),元素是不可以重复的。
|--HashSet: 底层数据结构是哈希表。地址相同的元素按同地址顺延。线程非同步
--------------------------------------------------------------------------------------------------
HashSet是如何保证元素的唯一性的呢?
是通过元素的两个方法:hashCode和equals来完成的。
如果元素的HashCode不同,才会判断equals是否为true;
如果元素的HashCode不同,不会调用equals;
!!!注意:
对于判断元素是否存在以及删除等操作,依赖的方法都是元素的hashCode和equals方法。
--------------------------------------------------------------------------------------------------
Set集合的功能和Collection是一致的。
add()添加操作返回的是boolean:
对于Set集合,如果已包含该元素,则返回false,否则返回true。
对于Collection集合或List集合,如果此collection或List由于调用而发生更改,则返回 true
***
因此,对于Set集合,要往容器中添加【自定义类对象】,改变元素相同判断条件,就需要重写equals()方法,并且还要重写自己的hashCode()方法。(因为比较的是哈希值)
并且使用迭代器时需要对自动提升的对象进行强制向下转型。
实例:
import java.util.*;
class Person
{
private String name;
private int age;
Person(String name,intage){
this.name =name;
this.age = age;
}
public StringgetName(){
returnthis.name;
}
public int getAge(){
return this.age;
}
public int hashCode(){
HashSetDemo.sop(this.name+"....hashcode");
//return 60;
returnthis.name.hashCode()+this.age*39;
//String类中有覆盖hashCode方法。*39是尽量保证哈希值的唯一性。
}
public booleanequals(Object obj){
if (!(objinstanceof Person))
returnfalse;
Person px =(Person)obj;
HashSetDemo.sop(this.name+":"+this.age+"..."+px.name+":"+px.age);
return(this.name == px.name&&this.age == px.age);
}
}
class HashSetDemo
{
public static voidmain(String[] args)
{
HashSet hs = newHashSet();
hs.add(new Person("mike",11));
hs.add(newPerson("mike",12));
hs.add(newPerson("mike",13));
hs.add(newPerson("mike",12));
//hs.add(newPerson("mike",14));
Iterator it =hs.iterator();
while(it.hasNext())
{
Person p= (Person)it.next();
sop(p.getName()+"..."+p.getAge());
}
}
public static voidsop(Object obj){
System.out.println(obj);
}
}
第二部分:TreeSet的使用
|--Set:元素是无序的(存入和取出的顺去不一定一致),元素是不可以重复的。
|--HashSet: 底层数据结构是哈希表。地址相同的元素按同地址顺延。线程非同步
|--TreeSet:可以对Set集合中的元素进行排序。
底层数据结构是:二叉树。
TreeSet保证元素唯一性的依据是:
compareTo方法return 0;
TreeSet排序的第一种方式:
让元素自身具备比较性,元素需要实现Comparable接口并覆盖compareTo方法。(自然顺序)
TreeSet排序的第二种方式:
当元素自身不具备比较性时,或者具备的比较性不是所需要的。这时需要让集合自身具备比较性。在集合初始化时,就有了比较方式。
定义一个比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。
【定义方法】:定义一个类,实现Comparator接口,覆盖compare方法。
当两种排序都存在时,以比较器为主。
【代码】需求:网TreeSet集合中存储自定义对象:学生。
而且想要按照学生的年龄进行排序。
谨记:
排序时,当主要条件相同时,一定要判断一下次要条件。
* // *
import java.util.*;
class TreeSetDemo
{
public static voidmain(String[] args)
{
TreeSet ts = newTreeSet(new MyCompare());
ts.add(newStudent("mike02",22));
ts.add(newStudent("mike07",20));
ts.add(newStudent("mike09",19));
ts.add(newStudent("mike01",19));
Iterator it =ts.iterator();
while(it.hasNext())
{
Student s= (Student)it.next();
System.out.println(s.getName()+"::"+s.getAge());
}
}
}
class Student //implements Comparable//该接口强制让学生具备比较性
{
private String name;
private int age;
Student(String name,int age){
this.name =name;
this.age = age;
}
public StringgetName(){
returnthis.name;
}
public int getAge(){
return this.age;
}
public intcompareTo(Object obj){
if(!(objinstanceof Student))
throw newRuntimeException("Not Student");
Student s = (Student)obj;
System.out.println(this.name+"...compareTo..."+s.name);
if(this.age>s.age)
return 1;
elseif(this.age<s.age)
return-1;
else //String类已经实现了Comparable接口
returnthis.name.compareTo(s.name);
}
}
//第二种排序方式
class MyCompare implements Comparator
{
public intcompare(Object o1,Object o2){
Student s1 =(Student)o1;
Student s2 = (Student)o2;
int num =s1.getName().compareTo(s2.getName());
if(num==0)
returns1.getAge()-s2.getAge();
return num;
}
}
* // *
【练习】:按照字符串长度排序。
字符串本身具有比较性,但是比较方式不是所需求的。
* /
import java.util.*;
class StrCompare implements Comparator
{
public intcompare(Object o1,Object o2){
String s1 =(String)o1;
String s2 =(String)
//使用基本数据类型包装类:Integer类的构造函数转成字符串。
int num = newInteger(s1.length()).compareTo(new Integer(s2.length()));
if(num == 0)
returns1.compareTo(s2);
return num;
}
}
class TreeSetTest
{
public static voidmain(String[] args){
TreeSet ts = newTreeSet(new StrCompare());
//也可以传递匿名内部类
ts.add("abcd");
ts.add("abcdef");
ts.add("abcdefgh");
ts.add("abcde");
ts.add("abcde");
Iterator it =ts.iterator();
while (it.hasNext())
{
sop(it.next());
}
}
public static voidsop(Object obj){
System.out.println(obj);
}
第一部分:泛型
/ *
泛型:
JDK1.5版本以后出现的新特性。用于解决安全问题,是一个安全机制。
好处:
1.讲运行时期出现的问题ClassCastCException,转移到了编译时期。
方便于程序员解决问题,让运行时期问题减少,程序更安全。
2.避免了强制类型转换的麻烦。
泛型格式:
通过<>来定义要操作的引用数据类型。
在使用java提供的对象时,什么时候使用泛型?
通常在集合框架中很常见,只要见到<>就需要建立泛型。<>就是用来接收类型的。
当使用集合时,将集合中要存储的数据类型作为参数传递给<>即可。
//相应的比较器Comparator或者接口Comparable也需要指定泛型
class MyCompare implements Comparator<String>
{
public intcompare(String s1,String s2){
int num = newInteger(s1.length()).compareTo(new Integer(s2.length()));
if (num == 0)
returns1.compareTo(s2);
return num;
}
}
---------------------------------------------------------------------
【泛型类】
【需求】:定义一个工具类,用于操作自定义类对象
泛型前做法:
class Tool
{
private Object obj;//
public voidsetObject(Object obj){
this.obj = obj;
}
public ObjectgetObject(){
return this.obj;
}
}
public Test
{
public static void main(String[] args{
Tool t = newTool();
t.setObject(newStudent());
Worker w =(Worker)t.getObject();
//这时编译通过,但是运行会产生ClassCastException
}
}
使用泛型:
class Utils<T >
{
private T t;//
public void setObject(T t){
this.t = t;
}
public T getObject(){
return this.t;
}
}
public Test
{
public static voidmain(String[] args){
Utils<Worker> u = new Utils<Worker>();
u.setObject(newStudent());
Worker w =u.getObject();
//这时编译会报错,并且省略了强转操作
}
}
-------------------
什么时候需要定义泛型类?
当类中需要操作的引用数据类型不确定的时候,早期定义Object来完成扩展。
现在利用定义泛型来完成扩展。
注意:只能是引用数据类型,而不是基本数据类型。
* // *
----------------------------------------------------------------------
【泛型方法】
泛型类定义的泛型,在整个类中有效,如果被方法使用,那么泛型类的对象明确要
操作的具体类型后,所有可以操作的类型就固定了。
为了让不同方法可以操作不同类型,而且类型还不确定。可以将泛型定义在方法上。
class Demo
{
public <T> voidshow(T t){
}
public <T> void print(T t){
}
}
【注意】:泛型类和泛型方法的同时定义不冲突,参数表示不同即可。
-----------------------------------------------------------------------
【静态方法泛型】
静态方法不可以访问类上定义的泛型,如果静态方法操作的应用数据类型不确定
可以将泛型定义在方法上。
public static <W> void method(W w){
}
书写格式错误:public <W> static void method(W w)
【注意】:泛型定义放在返回类型的前端。
-----------------------------------------------------------------------
【泛型接口】
interface Inter<T>
{
void show(T t);
}
//直接实现类型
class InterImp implements Inter<String>
{
public void show(Stringt){
sop("show :"+t);
}
}
//实现后依然为泛型
class InterImp<T> implements Inter<T>
{
public void show(T t){
sop("show :"+t);
}
}
*//*
--------------------------------------------------------------------------
【泛型限定】
1.通配符?,也可以理解为占位符
public static void printColl(ArrayList<?> al)//打印任意泛型
2.
public static void printColl(ArrayList<Person> al)
ArrayList al1 = new ArrayList<Student>()
printColl(al1)//编译失败
【这就相当于用法】:ArrayList<Person> al = new ArrayList<Student>();
Student虽继承Person,但是这种用法是错误的。ERROR!!!
此时若只想使用特定范围里的泛型,就需要泛型限定:
public static void printColl(ArrayList<? extends Person> al){
Iterator<? extendsPerson> it = al.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
3、**********************************************
<?> :不确定泛型,任意泛型
<? extends E> :可以接受E类型或E的子类型。上限限定
<? super E> :可以接受E类型或者E的父类型。下限限定 *************************************************
* /
import java.util.*;
class GenericDemo
{
public static voidmain(String[] args){
TreeSet<Student> ts = new TreeSet<Student>(new Comp());
ts.add(newStudent("sabc01"));
ts.add(newStudent("sabc04"));
ts.add(new Student("sabc02"));
ts.add(newStudent("sabc06"));
Iterator<Student> it = ts.iterator();
while(it.hasNext()){
System.out.println(it.next().getName());
}
TreeSet<Worker> ts1 = newTreeSet<Worker>(new Comp());
ts1.add(newWorker("wabc02"));
ts1.add(newWorker("wabc01"));
ts1.add(newWorker("wabc05"));
ts1.add(newWorker("wabc07"));
Iterator<Worker> it1 = ts1.iterator();
while(it1.hasNext()){
System.out.println(it1.next().getName());
}
/*ArrayList<Integer> al1 = new ArrayList<Integer>();
al1.add(4);
al1.add(7);
al1.add(1);
printColl(al1);*/
}
/ *通配符?可以表示不确定泛型
public static voidprintColl(ArrayList<?> al){
Iterator<?> it = al.iterator();
while(it.hasNext()){
System.out.println(it.next());
}//不能使用类型特有方法如length(),但是可以用toString()等通用方法。
}* /
}
class Comp implements Comparator<Person>//<? superStudent>
{
public int compare(Persons1, Person s2){
//只能用父类中包含的方法
returns1.getName().compareTo(s2.getName());
}
}
class Person
{
private String name;
Person(String name){
this.name =name;
}
public String getName(){
return name;
}
public StringtoString(){
return"person :"+name;
}
}
class Student extends Person
{
private String name;
Student(String name){
super(name);
}
}
class Worker extends Student
{
private String name;
Worker(String name){
super(name);
}
}