首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

黑马软件工程师_集合框架-Collection-Set(四)

2012-11-17 
黑马程序员_集合框架-Collection-Set(四)-------android培训、java培训、java学习型技术博客、期待与您交流!

黑马程序员_集合框架-Collection-Set(四)

-------android培训、java培训、java学习型技术博客、期待与您交流! ----------

         集合框架的顶层接口Collection下的子接口Set,和子接口List一样比较重要。

Set

    在Set集合中,有以下几个常子类,HashSet、TreeSet、LinkedHashSet.

       元素不能重复,无序,Set接口中的方法和collection的方法一样

HashSet

HashSet:内部实际结构是哈希表,是不同步的。

哈希表:将对象经过哈希算法计算成该对象的哈希值,并把哈希值存放在哈希表中,其实哈希值就相当于数组中的角标。所以在查找的时候直接根据哈希值查询,速度很快。

哈希表确定元素是否相同

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已略.

TreeSet

TreeSet:可以对集合中的元素进行排序,是不不同步的,

判断元素唯一性的方式:即使根据比较方法的返回结果是否是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

热点排行