黑马程序员_Set集合容器和泛型

android培训java培训、期待与您交流!


第一部分: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);

       }

}

 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值