黑马程序员系列第四篇 集合(1)

November 15, 2015

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

 

(前言:本篇文章主要依据毕向东老师的课程视频整理而成,如要详细学习,请观看毕老师视频  百度网盘链接地址:http://pan.baidu.com/s/1o6mwDzO

 

目录:1、集合概述      2、Collection、Iterator接口     3、List接口与其ArrayList、LinkedList、Vector子类   4、Set接口及其HashSet、TreeSet子类

 

1、集合概述 

 

下图为JDK中集合的框架设计图,我们主要使用的集合为黑色方框中的四种集合。

数组和集合的不同:集合中对象数量不定,而数组中对象数量必须是确定的。

ArrayList  底层数据存储结构是数组结构   特点:查询速度快,增删稍慢,线程不同步

LinkedList 底层数据结构是链表结构        特点:查询稍慢,增删快

Vector      底层是数组数据结构             特点:都很慢,线程同步,出现最早,已经被ArrayList替代了现在很少用

Set          集合中的元素是无序的(存入和取出的顺序不一定一致),元素不可以重复。

HashSet   底层数据结构是hash表

TreeSet    底层数据结构是二叉树\红黑树

 

2、Collection、Iterator接口 

迭代器 Iterator  是为了方便集合操作元素而定义。而且专门为List集合定义了特有的迭代器ListIterator(为Iterator接口的子接口)

注意:使用迭代器时,不可以再通过集合对象的方法操作集合中的对象,会发生ConcurrentModification异常。

两个基本接口中的方法很重要

代码演示了Collection方法的使用以及遍历的操作方式(例子很普通,主要看下遍历的操作方法)

 1 public class CollectionTest {
 2     public static void main(String[] args) {
 3         List d=new ArrayList();//新建集合、向集合中添加对象
 4         d.add("jake"); 
 5         d.add("alean");
 6         d.add("sam");           
 7         iteratorTest(d);
 8     }
 9     //如何使用ListIterator进行遍历操作对象
10     public static void iteratorTest(List c){
11            ListIterator it=c.listIterator();
12            while(it.hasNext()){
13                //ListIterator中添加
14                if(it.next()!=null){  
15                    it.add("nanjing");
16                }
17 //               ListIterator中修改
18 //               if(it.next()=="jake"){
19 //                   it.set("beokj");
20 //               }             
21            }
22            System.out.println(c);
23     }
24     //collection接口方法使用
25     public static void collectionMethods(){
26         Collection c=new ArrayList();
27         Collection d=new ArrayList();
28         //增加
29         d.add("jake"); d.add("alean");d.add("sam");
30         c.addAll(d);
31         //删除
32         //c.remove("jake");
33         //c.removeAll(c);
34         //c.clear();
35         System.out.println(c.isEmpty());
36         System.out.println(c+":size="+c.size());
37     }
38 }

 

3、List接口与其ArrayList、LinkedList、Vector子类

      ArrayList中涉及到比较集合中对象是否相同中用到的底层方法是集合中对象的equals()方法

      LinkedList中的方法  JDK1.6以后出现了替代getFirst()\getLast()\removeFirst()\removeLast()方法的

      offerFirst\offerLast\peekFirst()\peekLast()新方法,新方法的优势是集合中没有元素了不会出现NoSuchElementException异常

      Vector  有特有的枚举方式取数据。其实枚举和迭代是一样的,枚举的名称和方法名称过长,所以被迭代器取代了,仅做了解

   ArrayList 演示代码(除去集合中的重复对象)

 1 public class ArrayListDemo {
 2 
 3     public static void main(String[] args) {
 4         //新建一个ArrayList类型集合,向其中添加Person对象
 5          ArrayList al=new ArrayList();
 6         al.add(new Person("jack",12));
 7         al.add(new Person("jack",12));
 8         al.add(new Person("jack",11));
 9         al.add(new Person("jack2",12));
10         al.add(new Person("jack",12));
//除去al集合中的相同对象,打印结果
11 System.out.println(singleElement(al)); 12 } 13 //删除ArrayList集合中重复的元素 14 public static ArrayList singleElement(ArrayList arrays){ 15 ArrayList al=new ArrayList(); 16 Iterator ite=arrays.iterator(); 17 //通过while循环,在其中用ArrayList的contains方法判断是否重复 18 while(ite.hasNext()){ 19 Object obj=ite.next(); 20 if(!al.contains(obj)) 21 al.add(obj); 22 } 23 return al; 24 } 25 26 } 27 //Person类 28 class Person{ 29 private String name; 30 private int age; 31 //共有全参构造方法 32 public Person(String name, int age) { 33 super(); 34 this.name = name; 35 this.age = age; 36 } 37 public String getName() { 38 return name; 39 } 40 public void setName(String name) { 41 this.name = name; 42 } 43 public int getAge() { 44 return age; 45 } 46 public void setAge(int age) { 47 this.age = age; 48 } 49 //重写equals方法,自定义比较的依据,这里我们定义对象的姓名、年龄都相同时,对象才相等 50 public boolean equals(Object obj) { 51 Person per=(Person)obj; 52 if(!(obj instanceof Person)) 53 return false; 54 else 55 return per.name.equals(name) && per.age==age; 56 } 57 //重写toString方法,便于查看程序的运行结果 58 public String toString() { 59 return name+"::"+age; 60 } 61 62 }

 

LinkedList示例代码(用LinkedList模拟堆栈(先进后出)和队列(先进先出)数据结构)

 1 public class LinkedListDemo {
 2     public static void main(String[] args) {
 3         
 4         Queue queue=new Queue();
 5         queue.set("红");
 6         queue.set("黄");
 7         queue.set("蓝");
 8         queue.set("紫");
 9         
10         while(!queue.isNull()){
11             System.out.println(queue.get());
12         }
13     }
14 }
15 //模拟队列,先进先出
16 class Queue{
17     private LinkedList ll;
18     public  Queue(){
19          ll=new LinkedList();
20      }
21     public Object get(){
22         return ll.removeFirst();
23     }
24     public void set(Object obj){
25         ll.addLast(obj);
26     }
27     public boolean isNull(){
28         return ll.isEmpty();
29     }
30 }
31 //模拟堆栈-先进后出
32 class Stack{
33     private LinkedList ll;
34     public  Stack(){
35          ll=new LinkedList();
36      }
37     public Object get(){
38         return ll.removeLast();
39     }
40     public void set(Object obj){
41         ll.addLast(obj);
42     }
43     public boolean isNull(){
44         return ll.isEmpty();
45     }
46 }

 

 4、Set接口及其HashSet、TreeSet子类

HashSet 中比较的底层原理 : 先调用hashcode方法判断对象hash值是否相同,若相同,再调用对象那个的equels()方法,判断对象是否相同

实际开发中,新建集合中的对象时,都要重写对象的hashcode和equals方法

 

TreeSet : 可以对TreeSet集合中的元素进行自然排序。

第一种排序方式:比较原理是在集合元素中实现CompareTo接口

第二种排序方式:当元素自身不具备比较性时,可让集合具有比较性。方法:定义比较器(即实现了Comparator接口的类),将比较器对象作为参数传递给TreeSet集合的构造函数。

总结:两种方式中,第二种方式基于接口编程,拓展性好,比较常用。如果两种排序方式同时存在,系统使用第二种方式

 

 HashSet集合的代码示例

 1 public class HashSetDemo{
 2 
 3     public static void main(String[] args) {
 4          
 5         HashSet hs=new HashSet();
 6         hs.add(new Persons("Tom1",24));    
 7         hs.add(new Persons("Tom1",25));  
 8         hs.add(new Persons("Tom1",24));  
 9         //遍历器来查询集合中对象
10         Iterator ite=hs.iterator();
11         while(ite.hasNext())
12             System.out.println(ite.next());
13     }
14 }
15 //Person类
16 class Persons{
17     private String name;
18     private int age;
19     //共有全参构造方法
20     public Persons(String name, int age) {
21         super();
22         this.name = name;
23         this.age = age;
24     }
25     public String getName() {
26         return name;
27     }
28     public void setName(String name) {
29         this.name = name;
30     }
31     public int getAge() {
32         return age;
33     }
34     public void setAge(int age) {
35         this.age = age;
36     }
37     //重写hashCode方法,自己定义判断
38     public int hashCode(){
39         return name.hashCode()+age;
40     }
41   //重写equals方法,自定义比较的依据,这里我们定义对象的姓名、年龄都相同时,对象才相等
42     public boolean equals(Object obj) {
43         Persons per=(Persons)obj;         
44             if(!(obj instanceof Persons))                
45                 return false;
46             else         
47                 return per.name.equals(name) && per.age==age;
48     }
49   //重写toString方法,便于查看程序的运行结果
50     public String toString() {
51         return name+"::"+age;
52     }    
53 }

 

TreeSet代码示例

同时实现了两种排序方式。验证了两种排序方式共存是,系统采用何种方式

 1 public class TreeSetDemo {
 2 //两种比较方式共存,系统采用比较器的比较方式
 3     public static void main(String[] args) {
 4         
 5        TreeSet ts=new TreeSet(new comparator());
 6         ts.add(new Persont("bbama1",22));
 7         ts.add(new Persont("abama3",22));
 8         ts.add(new Persont("abama2",24));
 9         ts.add(new Persont("abama3",21));
10         
11         Iterator ite=ts.iterator();
12         while(ite.hasNext()){
13             System.out.println(ite.next());
14         }
15     }
16 
17 }
18 //实现比较器,规定元素按照姓名排序,姓名相同的按年龄排序
19 class comparator implements Comparator{
20     @Override
21     public int compare(Object o1, Object o2) {
22         Persont p1=(Persont)o1;
23         Persont p2=(Persont)o2;
24         int i=p1.getName().compareTo(p2.getName());
25         if(i==0)
26             return p1.getAge()-p2.getAge();
27         else return i;
28     }    
29 }
30 //Person类,规定元素按照年龄排序,年龄相同的按姓名排序
31 class Persont implements Comparable<Persont>{
32     private String name;
33     private int age;
34     //共有全参构造方法
35     public Persont(String name, int age) {
36         super();
37         this.name = name;
38         this.age = age;
39     }
40     public String getName() {
41         return name;
42     }
43     public void setName(String name) {
44         this.name = name;
45     }
46     public int getAge() {
47         return age;
48     }
49     public void setAge(int age) {
50         this.age = age;
51     }
52 
53   //重写toString方法,便于查看程序的运行结果
54     public String toString() {
55         return name+"::"+age;
56     }
57 @Override
58 public int compareTo(Persont per) {
59     if(age>per.age)
60     return 1;
61     if(age==per.age){
62         return name.compareTo(per.name);
63     }    
64     else
65         return -1;
66 }    
67 }

 

 

       初学者难免错误,欢迎评判指教,持续更正ing...........

 

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