集合框架

本文详细介绍了Java集合框架的结构和特点,包括List、Set、Map等核心接口及其具体实现类,如ArrayList、HashSet、HashMap等,并阐述了它们的内部工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------

14,集合框架

14.1集合的由来

对于同一种类型的数据,我们可以用数组存储,数组多了,还可以用二维数组存;不同类型的数据可以使用StringBufferStringBuilder;那么如果对象多了,就可以用集合存储。

java中,存在不同的集合容器,对这些集合进行向上抽取,就形成了集合框架。

 

集合的特点:

1,集合是存储对象的容器。

2,集合的长度是可变的。

3,集合不能存储基本数据类型值。

 

14.2集合框架结构图

 

 Collection<E>单列集合的根接口,Collection<E>常用两大体系List,Set

List接口常用子类:Vector<E>,ArrayList<E>,LinkedList<E>.

Set接口常用子类:HashSet<E>,TreeSet<E>,LinkedHashSet<E>.

Map<K,V>双列集合的根接口,存储的都是键值对,存在着键值对的映射关系,Map<K,V>常用子类有:TreeMap<K,V>,HashMap<K,V>,Hashtable<K,V>及其子类Properties集合(是一个可以结合IO流使用的集合)

 

14.3 Collection接口及Iterator迭代器原理

Collection接口是单列集合的根接口,内部封装了对所有单列集合操作的共性方法,不同的集合对集合中元素的内部操作方式不尽相同,Collection集合的子类通过复写和定义子类的特有内容,实现对不同集合的操作。

Iterator迭代器:Java中每个集合容器的内部数据结构不同,集合元素的取出方式也不同,对这些集合元素的取出方式进行不断的向上抽取,抽取为一个共性的取出元素的抽象方法。这个方法就是Collection接口中的iterator()方法,Collection集合的子类通过调用此方法,就可以获取Iterator迭代器对象,通过Iterator迭代器就可以完成取出元素的操作。

Iterator迭代器是由集合中的内部类实现的,每个集合的内部数据结构不同,集合通过调用iterator()方法,iterator()方法中,创建了实现Iterator接口的内部类对象。并返回这个对象,内部类中覆写了Iterator接口中的元素取出方法,如:hasNext(),itNext(),建立集合自己的元素取出方式。

14.4 List<E>集合

List集合特点:允许元素重复,有序(元素存入和取出顺序一致)

常用子类:

Vector 集合特点:jdk 1.0,不常用,内部是数组数据结构,是同步的,线程安全,效率低。支持包括null在内的所有元素。(被ArrayList替代)。
ArrayList集合特点:jdk 1.2 ,内部是可变长度数组数据结构,不同步,增删慢,但查询速度快。支持包括null在内的所有元素。
LinkedList集合特点:jdk 1.2 ,内部是链表数据结构,不同步,增删快,但查询速度慢。支持null及所有元素。

 

1.      Vector集合

Vector内部是数组数据结构,可变长度数组,这个集合,多线程是同步的,所以效率会低一些,现在,很少用到,此集合有一个元素取出的特有方式就是Enumeration<E>枚举,通过调用elements()方法,返回Enumeration<E>对象,再调用枚举对象的方法,取出元素,同样这个集合也具有iterator()listIterator()两种迭代器。对于此集合来说,有三种元素的取出方。

示例代码:

import java.util.Enumeration;

import java.util.Vector;

public class VectorDemo {

   public static void main(String[] args) {

      //1,创建Vector集合

      Vector<String> vector=new Vector<String>();

      //2,添加String类型的元素

      vector.add("abc1");

      vector.add("abc2");

      vector.add("abc3");

      vector.add("abc4");

      //3,取出元素

      for(Enumeration<String> en=vector.elements();en.hasMoreElements();){

         String s=en.nextElement();

         System.out.println("集合元素:"+s);

      }     

   }

}

/*

  集合元素:abc1

  集合元素:abc2

  集合元素:abc3

  集合元素:abc4

*/


 

IteratorlistIterator有什么不同?

Iterator迭代器对象,只能遍历或取出集合中的元素,而listIterator迭代器,可以实现在遍历或取出元素的同时,对集合进行修改,增加,删除等操作,并且可以从后往前遍历或取出集合元素。

如:

import java.util.ListIterator;

import java.util.Vector;

public class VectorDemo {

   public static void main(String[] args) {

      //1,创建Vector集合

      Vector<String> vector=new Vector<String>();

      //2,添加String类型的元素

      vector.add("abc1");

      vector.add("abc2");

      vector.add("abc3");

      vector.add("abc4");

      //3,取出元素,使用ListIteraor迭代器

      for(ListIterator<String> li=vector.listIterator();li.hasNext();){

         String s=li.next();

         li.set("abc5");//取出元素的同事,修改集合元素。

         System.out.println("集合元素:"+s);       

      }     

      System.out.println(vector.toString());

   }

}

/*

  集合元素:abc1

  集合元素:abc2

  集合元素:abc3

  集合元素:abc4

  [abc5, abc5, abc5, abc5]

*/

2.      ArrayList集合

此集合内部是数组数据结构,是可变长度数组,不支持线程同步所以效率要高一些,此集合的出现目的就是替代Vector集合,因为内部是数组数据结构,所以,元素的查询速快,但元素的增删速度慢。ArrayList集合的元素取出可以通过调用,iterator()listIterator()方法,获取IteratorListIterator两个迭代器对象,再通过迭代器对象取出元素。

如: 

import java.util.ArrayList;

import java.util.Iterator;

import java.util.ListIterator;

public class ArrayListDemo {

   public static void main(String[] args) {

      //1,创建ArrayList集合

      ArrayList<String> al=new ArrayList<String>();

      //2,添加String类型的元素

      al.add("abc1");

      al.add("abc2");

      al.add("abc3");

      al.add("abc4");

      //3,取出元素,使用Iteraor迭代器

      for(Iterator<String>it=al.iterator();it.hasNext();){

         String s=it.next();

         System.out.println("集合元素:"+s);    
      }      

   }

}

/*

  集合元素:abc1

  集合元素:abc2

  集合元素:abc3

  集合元素:abc4

*/

 

3,LinkedList集合

此集合内部是链表数据结构,不支持线程同步,因为内部数据结构的原因,其增删元素的速度快,但查询速度慢。

元素的取出也可以通过调用iterator()listIterator()方法,获取迭代器对象IteratorlistIterator,通过对象的元素取出方法,取出元素。

如:

import java.util.Iterator;

import java.util.LinkedList;

public class ArrayListDemo {

   public static void main(String[] args) {

      //1,创建LinkedList集合

      LinkedList<Integer> link=new LinkedList<Integer>();

      //2,添加String类型的元素

      link.add(123);

      link.add(345);

      link.add(456);

      link.add(789);

      //3,取出元素,使用ListIteraor迭代器

      for(Iterator<Integer>it=link.iterator();it.hasNext();){

         Integer i=it.next();

         System.out.println("集合元素:"+i);       

      }           

   }

}

/*

集合元素:123

集合元素:345

集合元素:456

集合元素:789

*/

 

练习:去除ArrayList集合中重复的元素。

思路:

1,因为ArrayList集合中的元素是允许重复的。

2,可以,再创建一个临时的ArrayList集合,遍历ArrayList集合,通过临时的ArrayList集合调用contains()判断,这个空集合,是否包含遍历的元素,如果包含就不添加,否则,添加到临时的集合中。返回临时的集合,获取一个不含重复元素的ArrayList集合。

如:

import java.util.ArrayList;

import java.util.Iterator;

public class ArrayListDemo {

   public static void main(String[] args) {

      //创建集合

      ArrayList<String>al=new ArrayList<String>();

      //添加元素

      al.add("abc1");

      al.add("abc2");

      al.add("abc2");

      al.add("abc1");

      al.add("abc4");

      al.add("abc5");

      //调用去除重复元素的方法

      ArrayList al1=deleteElements(al);

      //打印去除重复元素后的集合

      System.out.println("去出重复元素后:"+al1);  

   }

 

   public static ArrayList deleteElements(ArrayList<String> al) {

         //1,创建临时容器ArrayList

         ArrayList<String> temp=new ArrayList<String>();

         //2,遍历包含元素的集合

         for (String s:al) {

            if(!temp.contains(s)){//contains()方法,实际是调用了equals()方法

                temp.add(s);//不包含时,就添加到临时集合ArrayList中。

            }           

         }

      return temp;

   }

}

 

//去出重复元素后:[abc1, abc2, abc4, abc5]


 

14.5 Set<E>集合
Set集合的特点:不允许元素重复(与List集合相反),保证元素的唯一性,无序(存取顺序一致或不一致。LinkedHashSet可维持存取顺序一致,TreeSet集合可以对元素进行自然排序,但元素本身要实现Comparable接口)

常用子类:

HashSet集合特点:jdk 1.2内部是哈希表数据结构,不同步,允许null元素。此集合通过内部的哈希算法来确定元素的存储位置,因为不允许元素重复,所以,每存入一个元素都会与前一次存入的元素进行比较,是通过调用元素的hashCode()方法和equals()方法来进行比较的。(这里要注意的是:equals()方法比较的是内容,而不是地址,所以当在HashSet集合中存入自定义元素时,如果要保证元素的唯一性,必须要覆写hashCode()方法和equals()方法。) 

LinkedHashSet集合:LinkedHashSet是HashSet的子类,能保证存取顺序一致。允许null元素。 

TreeSet集合特点:jdk 1.2内部是二叉树数据结构,不同步,允许null元素。TreeSet与HashSet集合中的hashCode(),equals()方法无关。TreeSet集合可以对元素进行自然排序,因为 TreeSet集合是通过调用元素的compareTo()方法来,进行排序和判断元素是否相同的,而compareTo()方法是由元素内部实现Comparable接口,并覆写compareTo()完成的。所以TreeSet集合中的元素,必须要实现Comparable接口,覆写 CompareTo()方法,常用的类一般都实现了Comparable接口,例:如果在TreeSet集合中存储自定义对象,那么这个自定义的类必须要实现Comparable接口,并且覆写CompareTo方法,使其具有比较性。

 1,HashSet集合

内部是哈希表数据结构,每次添加一个元素,都会调用元素的hashCode()方法,获取元素的哈希值确定元素的存储位置,如果有两个元素的哈希值相同,会再次调用equals()方法,比较这两个元素的内容,如果内容不同,会延伸位置存储,相同则不存。Java自身的类内部已经完成了对hashCode()equals()方法的覆写,所以不需要再进行覆写。而对于自定义的一些类,作为元素存储到HashSet时,必须要覆写这两个方法。

为什么自定义的类必须覆写hashCode()equals()方法呢?

因为,Java中所有的类都继承Object类,如果自定义的类没有覆写hashCode()和equals(),那么使用的就是Object类中的hashCode()equals()方法,Ojbect类中的这两个方法,是内部实现的。而覆写的目的是建立自定义类的自身的hashCode()equals().

如:

import java.util.HashSet;

import java.util.Iterator;

 

 

public class HashSetDemo {

   public static void main(String[] args) {

      HashSet<String> hs=new HashSet<String>();

      hs.add("abc1");

      hs.add("abc1");//添加重复元素

       hs.add("abc2");

      hs.add("abc3");

      hs.add("abc4");

      for (Iterator<String> it=hs.iterator();it.hasNext();) {

         String str=it.next();

         System.out.println(str);    

      }

   }

}

/*

打印结果:

abc1

abc4

abc2

abc3

*/


 

集合中存储的String类型元素,重复的元素无法添加到集合中。这是因为,String内部实现了hashCode()和equals()的覆写。

 

HashSet存储自定义对象:

如:

 

import java.util.HashSet;

import java.util.Iterator;

public class HashSetDemo {

   public static void main(String[] args) {

      HashSet<Person> hs=new HashSet<Person>();

      hs.add(new Person("lisi",24));

      hs.add(new Person("lisi",24));//添加重复元素

      hs.add(new Person("zhangsan",23));

      hs.add(new Person("zhangsan",23));//添加重复元素

      hs.add(new Person("xiaoqiang",20));

      hs.add(new Person("wangwu",21));

      

      for (Iterator<Person> it=hs.iterator();it.hasNext();) {

         Person p=it.next();

         System.out.println(p.getName()+"::"+p.getAge());     

      }

   }

}

class Person{//自定义Person类

   private int age;

   private String name;

   public int getAge() {

      return age;

   }  

   public String getName() {

      return name;

   }  

   Person(String name,int age){

      this.name=name;

      this.age=age;

   }  

}

/*

 打印结果:

zhangsan::23

wangwu::21

zhangsan::23

lisi::24

lisi::24

xiaoqiang::20

可见,重复元素也被添加进了HashSet集合

*/


 

HashSet集合中存储的自定义对象Person,为什么可以重复呢?因为自定义的Person类中,并没有覆写hashCode()equals()方法,而是直接调用了父类Object类中的hashCode()equals()方法,Object类的hashCode()是获取对象的哈希值,而每次new的对象,哈希值都是不一样的,且Object类中的equals()方法比较也是对象的地址,所以,虽然在HashSet集合存储了具有相同内容的对象,但是他们的哈希值和地址都是不同的,所以当HashSet集合在调用PersonhashCode()和equals()实际上是调用了Object中的这两个方法,因为值得不同,所以认为是不同的元素。

可见,对于自定义对象要想保证元素不重复,就要覆写Object类的hashCode()equals()方法,建立自定义元素的特有比较方式。

如:

import java.util.HashSet;

import java.util.Iterator;

public class HashSetDemo {

   public static void main(String[] args) {

      HashSet<Person> hs=new HashSet<Person>();

      hs.add(new Person("lisi",24));

      hs.add(new Person("lisi",24));//添加重复元素

      hs.add(new Person("zhangsan",23));

      hs.add(new Person("zhangsan",23));//添加重复元素

      hs.add(new Person("xiaoqiang",20));

      hs.add(new Person("wangwu",21));  

      for (Iterator<Person> it=hs.iterator();it.hasNext();) {

         Person p=it.next();

         System.out.println(p.getName()+"::"+p.getAge());        

      }

   }

}

class Person{//自定义Person类

   private int age;

   private String name;

   public int getAge() {

      return age;

   }  

   public String getName() {

      return name;

   }  

   Person(String name,int age){

      this.name=name;

      this.age=age;

   }

   public int hashCode(){//覆写hashCode方法,通过年龄和姓名的哈希值进行比较。

      return this.age+name.hashCode()*37;

   }

   public boolean equals(Object obj){//覆写equals()方法,对姓名和年龄进行比较。

      if(this==obj)

         return true;

      if(!(obj instanceof Person))

         throw new ClassCastException("类型不匹配!");

      Person p=(Person)obj;    

      return this.name.equals(p.name)&&this.age==p.age;    

   }  

}

/*

 打印结果:

zhangsan::23

wangwu::21

xiaoqiang::20

lisi::24

 

可见,重复元素没有被添加。

*/


 

总结:HashSet集合存储自定义类型的元素时,要覆写hashCode()equals()方法,完成自定义类型元素的特有比较方式,保证存储到HashSet集合中的唯一性。否则,不能保证唯一性。

2.LinkedHashSet集合

LinkedHashSet集合是HashSet的子类,此集合可以保证Set集合的有序性,实现元素的存和取的顺序一致。其他与hashSet集合相同。

如:

import java.util.Iterator;

import java.util.LinkedHashSet;


public class HashSetDemo {

   public static void main(String[] args) {

      LinkedHashSet<String> lhs=new LinkedHashSet<String>();

      lhs.add("abc1");

      lhs.add("abc2");

      lhs.add("abc3");

      lhs.add("abc4");

      lhs.add("abc5");

      for (Iterator<String> it=lhs.iterator();it.hasNext();) {

         String str=it.next();

         System.out.println(str);       

      }

   }

}

/*

打印结果:

abc1

abc2

abc3

abc4

abc5

元素的存入顺序和取出顺序一致。

*/


3.TreeSet集合

此集合是内部二叉树数据结构,集合可以实现对元素的自然排序,前提是元素必须实现Comparable接口,那些已经实现Comparable接口,并覆写了compareTo()方法的java类,就已经具备了比较性,但是自定义的元素,必须要实现Comparable接口,并覆写compareTo()方法,TreeSet集合与元素的hashCode()equals()方法无关。

TreeSet集合中对元素进行排序的两种方式:

1)自定义元素实现Comparable接口,覆写compareTo()方法,建立自定义元素的特有排序特点。这里要注意元素比较的主要条件和次要条件,都进行判断。

如:存储自定义对象Person

import java.util.Iterator;

import java.util.LinkedHashSet;

import java.util.TreeSet;

 

 

public class HashSetDemo {

   public static void main(String[] args) {

      TreeSet<Person> ts=new TreeSet<Person>();

      ts.add(new Person("lisi",23));

      ts.add(new Person("zhangsan",20));

      ts.add(new Person("wangwu",29));

      ts.add(new Person("xiaoqiang",27));

      for (Iterator<Person> it=ts.iterator();it.hasNext();) {

                Person p=it.next();

                System.out.println(p.getName()+"::"+p.getAge());

      }

   }

}

class Person implements Comparable{//自定义Person类实现Comparable接口

   private int age;

   private String name;

   public int getAge() {

      return age;

   }  

   public String getName() {

      return name;

   }  

   Person(String name,int age){

      this.name=name;

      this.age=age;

   }

   

   @Override

   public int compareTo(Object o) {//覆写compareTo()方法

      Person p=(Person)o;

      int temp=this.age-p.age;

      return temp==0?this.name.compareTo(p.name):temp;//先判断年龄,年龄相同,再比较姓名。

   }  

}

/*

 打印结果:

zhangsan::20

lisi::23

xiaoqiang::27

wangwu::29

 

按照年龄进行了排序。

*/

 

2)如果某些自定义的元素,不能被操作,因为TreeSet集合的构造函数中,可以传入实现了Comparator接口的自定义比较器,可以让集合具备比较性,对元素进行排序。

如:

import java.util.Comparator;

import java.util.Iterator;

import java.util.TreeSet;

 

public class TreeSetDemo {

 

   public static void main(String[] args) {

      TreeSet<Person> ts=new TreeSet<Person>(new CompByAge());//要让集合具有比较性,必须传入比较器

      ts.add(new Person("lisi",23));

      ts.add(new Person("zhangsan",20));

      ts.add(new Person("wangwu",29));

      ts.add(new Person("xiaoqiang",27));

      for(Iterator<Person> it=ts.iterator();it.hasNext();){

         Person p=it.next();

         System.out.println(p.getName()+":"+p.getAge());

      }

   }

}

class Person{//自定义Person类,并没有实现Comparable接口

   private int age;

   private String name;

   public int getAge() {

      return age;

   }  

   public String getName() {

      return name;

   }  

   Person(String name,int age){

      this.name=name;

      this.age=age;

   }  

}

class CompByAge implements Comparator<Person>{//自定义一个比较器

 

   @Override

   publicint compare(Person o1, Person o2) {

      int temp=o1.getAge()-o2.getAge();

      return temp==0?o1.getName().compareTo(o2.getName()):temp;//定义比较的主要次要条件。

   }

   

}

/*

打印结果:

zhangsan:20

lisi:23

xiaoqiang:27

wangwu:29

 

*/


 

总结:TreeSet集合排序方法和判断元素是否相同可以有两种方式:

      (1)让元素具备比较性,就要元素去实现Comparable接口并覆写CompareTo()方法。

      (2)如果元素不是自己定义的,比如一个Person类,那么如果这个Person类没有去实现Comparable接口,这样Person对象就不具备比较性,这种情况我们可以采取第二种方式,就是让TreeSet集合具备比较性,因为TreeSet集合的构造函数中,可以传入比较器参数,所以我们可以自定义一个类并实现Comparator接口,这样就自定义了一个比较器,把这个比较器作为参数传递给TreeSet集合的构造函数,实现对元素的比较,完成排序。

 

14.6 Map<K,V>集合

Map集合是双列集合,集合中元素都是以键值对的形式存在的,且Map集合中必须保证键是唯一的,如果有相同的键存在,则值会被覆盖。

常用子类:

Hashtable:内部是哈希表数据结构,此集合不支持空键和空值,线程是同步的,所以相对效率要低,很少用到。

Hashtable子类Properties:此集合特点:1,键和值都是字符串类型。2,可以结合IO流使用,从流上获取数据和把集合中的数据保存到流上。

HashMap:内部是哈希表数据结构,支持空键和空值,线程不同步,效率高。

TreeMap:内部是二叉树数据结构,支持空键和空值,线程不同步。

1,Properties集合

 

此集合中键和值必须是字符串类型,没有泛型声明,元素的添加可以使用其特定的方法,setProperty(String key,String value);元素的取出可以使用其特定方法,stringPropertyNames()此方法返回一个Set<String key>集合的键集,再通过getProperty(String key),获取键对应的值。Properties集合,多用于对键值对形式的配置文件操作,因为它可以结合IO流,通过自己的特有方法,load()store()方法,从字节或字符流上获取数据到集合,也可以集合中的数据保存在字节流或字符流上,实现持有化存储。

如:读取一个配置文件,修改后,再进行存储。

/*

zhangsan=23

lisi=34

wangwu=30

zhaoliu=20

xiaoqiang=24

*/

以上是配置文件信息,现在通过Properties将xiaoqiang的值改为:30

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.File;

import java.io.FileReader;

import java.io.FileWriter;

import java.io.IOException;

import java.util.Properties;

 

//需求:读取一个配置文件,修改信息后,再存储到文件中。

publicclass Properties练习 {

   publicstaticvoid main(String[] args) throws IOException {

      modifiConfile("d:\\confile.properties");

}

 

   publicstaticvoid modifiConfile(String filename) {

      //1,将接收的字符串路径封装成File对象

      File file=new File(filename);

      //2,创建一个Properties集合

      Properties prop=new Properties();

      //3,对字符流初始化

      BufferedReader br=null;

      BufferedWriter bw=null;

      try {

         br=new BufferedReader(new FileReader(file));

         prop.load(br);//从字符流上获取关联的配置文件数据

         prop.setProperty("xiaoqiang", "30");//修改xiaoqiang的值为30

         bw=new BufferedWriter(new FileWriter(file));//创建字符输出流

         prop.store(bw, "name+age");//将修改后的数据再保存到流上,更改配置文件信息。

      } catch (IOException e) {

         e.printStackTrace();

      }finally{

         if(bw!=null)

         try {

            bw.close();

         } catch (IOException e) {

            e.printStackTrace();

         }

         if(br!=null)

         try {

            br.close();

         } catch (IOException e) {

            e.printStackTrace();

         }

      }

   }

}

/*

修改后的配置文件信息

#name+age

#Thu Oct 24 22:29:38 CST 2013

xiaoqiang=30

zhangsan=23

lisi=34

zhaoliu=20

wangwu=30

*/


2,HashMap<K,V>集合

此集合内部是哈希表数据结构,为了保证键的唯一性,需要调用键的hashCode()equals()方法,比如一些自定的元素,则必须要完成对 hashCode()equals()方法的覆写,否则不能保证键的唯一性。此集合与Hashset集合相似,其实HashSet内部就是调用了HashMap的细节操作。

元素的添加可以使用put(k,v),元素的取出可以调用keySet()entrySet()方法,返回一个包含键或包含键值对的Set集合,再过Set集合的迭代器取出元素。

如:存储自定义对象Person

import java.util.HashMap;

import java.util.Iterator;

import java.util.Map;

 

public class HashMapDemo {

 

   public static void main(String[] args) {

      HashMap<Person,String> hm=new HashMap<Person,String>();

      hm.put(new Person("lisi",23),"北京");

      hm.put(new Person("lisi",23),"北京");//存储了重复的元素。

      hm.put(new Person("zhangsan",20),"上海");

      hm.put(new Person("wangwu",29),"南京");

      hm.put(new Person("xiaoqiang",27),"重庆");

   for(Iterator<Map.Entry<Person,String>>it=hm.entrySet().iterator();it.hasNext();){//取出集合中的元素

         Map.Entry<Person, String> me=it.next();

         Person key=me.getKey();

         String value=me.getValue();

         System.out.println(key.getName()+":"+key.getAge()+":"+value);

      }
   }
}

class Person{//自定义Person类

   private int age;

   private String name;

   public int getAge() {

      return age;

   }  

   public String getName() {

      return name;

   }  

   Person(String name,int age){

      this.name=name;

      this.age=age;

   }  

}

/*

打印结果:

wangwu:29:南京

lisi:23:北京

zhangsan:20:上海

xiaoqiang:27:重庆

lisi:23:北京

这里可以发现,出现了同样的键。

 */

HashMap集合中存储了相同的自定义元素,为什么键不能保证唯一呢?

这是因为HashMap要保证键的唯一性,必须要覆写hashCode()equals()方法。所以,Person类中必须要完成对Object类中这两个方法的覆写,建立自定义Person对象元素的特定比较方式。

如: 

import java.util.HashMap;

import java.util.Iterator;

import java.util.Map;

 

public class HashMapDemo {

 

   public static void main(String[] args) {

      HashMap<Person,String> hm=new HashMap<Person,String>();

      hm.put(new Person("lisi",23),"北京");

      hm.put(new Person("lisi",23),"北京");//存储了重复的元素。

       hm.put(new Person("zhangsan",20),"上海");

      hm.put(new Person("wangwu",29),"南京");

      hm.put(new Person("xiaoqiang",27),"重庆");

   for(Iterator<Map.Entry<Person,String>>it=hm.entrySet().iterator();it.hasNext();){//取出集合中的元素

         Map.Entry<Person, String> me=it.next();

         Person key=me.getKey();

         String value=me.getValue();

         System.out.println(key.getName()+":"+key.getAge()+":"+value);

      }

   }

 

}

class Person{//自定义Person类

   private int age;

   private String name;

   public int getAge() {

      return age;

   }  

   public String getName() {

      return name;

   }  

   Person(String name,int age){

      this.name=name;

      this.age=age;

   }

   @Override

   public int hashCode() {//覆写hashCode()

      final int prime = 31;

      int result = 1;

      result = prime * result + age;

      result = prime * result + ((name == null) ? 0 : name.hashCode());

      return result;

   }

   @Override

   public boolean equals(Object obj) {//覆写equals()

      if (this == obj)

         return true;

      if (obj == null)

         return false;

      if (getClass() != obj.getClass())

         return false;

      Person other = (Person) obj;

      if (age != other.age)

         return false;

      if (name == null) {

         if (other.name != null)

            return false;

      } elseif (!name.equals(other.name))

         return false;

      return true;

   }  

   

}

/*

打印结果:

xiaoqiang:27:重庆

zhangsan:20:上海

wangwu:29:南京

lisi:23:北京

 

没有重复的键,保证了键的唯一性。

 */

 


 

3,TreeMap<K,V>集合

此集合内部是二叉树数据结构,可以实现对键的自然排序,但是如果是自定义的元素必须要实现Comparable接口,覆写compareTo()方法,或者,自定义比较器,实现Comparator接口,覆写compare()方法,传给TreeMap构造函数。才能完成对自定义元素的排序。

(1)     自定义元素实现Comparable接口,覆写compareTo()方法,让元素具备比较性。

import java.util.Iterator;

import java.util.Map;

import java.util.TreeMap;

 

public class TreeMapDemo {

 

   public static void main(String[] args) {

      TreeMap<Person,String>ts=new TreeMap<Person,String>();

         ts.put(new Person("lisi",23),"北京");

         ts.put(new Person("zhangsan",20),"上海");

         ts.put(new Person("wangwu",29),"南京");

         ts.put(new Person("xiaoqiang",27),"重庆");

   for(Iterator<Map.Entry<Person,String>>it=ts.entrySet().iterator();it.hasNext();){//取出集合中的元素

         Map.Entry<Person, String> me=it.next();

         Person key=me.getKey();

         String value=me.getValue();

         System.out.println(key.getName()+":"+key.getAge()+":"+value);

      }

      

   }

 

}

class Person implements Comparable<Person>{//自定义Person类实现Comparable接口

   private int age;

   private String name;

   public int getAge() {

      return age;

   }  

   public String getName() {

      return name;

   }  

   Person(String name,int age){

      this.name=name;

      this.age=age;

   }

   @Override

   publicint compareTo(Person o) {//覆写compareTo方法

      int temp=this.getAge()-o.getAge();

      return temp==0?this.getName().compareTo(o.getName()):temp;//先比较年龄,再比较姓名

   }  

   

}

/*

打印结果:

zhangsan:20:上海

lisi:23:北京

xiaoqiang:27:重庆

wangwu:29:南京

 */

 


 

(2)     自定义比较器,作为参数传递给TreeMap的构造函数,让集合具备比较性.

。

import java.util.Comparator;

import java.util.Iterator;

import java.util.Map;

import java.util.TreeMap;

 

public class TreeMapDemo {

 

   public static void main(String[] args) {

      TreeMap<Person,String>ts=new TreeMap<Person,String>(new Comparator<Person>(){

 

         @Override

         publicint compare(Person o1, Person o2) {

            int temp=o1.getAge()-o2.getAge();

            return temp==0?o1.getName().compareTo(o2.getName()):temp;

         }});//这里直接使用匿名内部类,创建Comparator接口子类对象,并覆写compare方法。

         ts.put(new Person("lisi",23),"北京");

         ts.put(new Person("zhangsan",20),"上海");

         ts.put(new Person("wangwu",29),"南京");

         ts.put(new Person("xiaoqiang",27),"重庆");

   for(Iterator<Map.Entry<Person,String>>it=ts.entrySet().iterator();it.hasNext();){//取出集合中的元素

         Map.Entry<Person, String> me=it.next();

         Person key=me.getKey();

         String value=me.getValue();

         System.out.println(key.getName()+":"+key.getAge()+":"+value);

      }

      

   }

 

}

class Person{//自定义Person类

   private int age;

   private String name;

   public int getAge() {

      return age;

   }  

   public String getName() {

      return name;

   }  

   Person(String name,int age){

      this.name=name;

      this.age=age;

   }  

}

/*

打印结果:

zhangsan:20:上海

lisi:23:北京

xiaoqiang:27:重庆

wangwu:29:南京

 */


 

 

总结:集合是用来存储对象的不同的集合其内部数据结构的不同,元素的操作方式也不同,单例集合中:List及其子类允许元素重复,Set集合不允许元素重复,Map要保证键的唯一。他们都有各自的判断元素是否相同的方式。其中Set集合的TreeSet,HashSet和 Map 集合的TreeMap,HashMap很相似,只是一个单例集合,一个是双例集合,元素保证唯一的方式基本一样。

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值