你的位置:首页 > Java教程

[Java教程]java基础——集合


集合与数组的区别:

 1.数组是固定长度的;集合的长度是可变的。

 2.数组可以存储基本数据类型,也可以存储引用数据类型;集合只能存储引用数据类型。

 3.数组存储元素必须是同一个数据类型;集合存储的对象可以是不同数据类型。

 java集合主要有3种重要的类型:

 ●List:是一个有序集合,可以存放重复的数据。

 ●Set: 是一个无序集合,不允许存放重复的数据。  

 ●Map: 是一个无序集合,集合中包含一个键对象和一个值对象,  键对象不允许重复,值对象可以重复。

 

下面是集合继承结构图-Collection部分,从图中可以很清楚的知道Collection接口下的子接口与实现类的关系。

 Collection集合的常用方法:

 boolean add(Object o): 向集合中添加元素

 boolean addAll(Collection c):把集合c中的元素添加到指定的集合中

 void clear():清空集合

 boolean isEmpty(): 判断集合中是否有元素

 Iterator iterator(): 获取集合所依赖的迭代器对象

 boolean contains(Object o): 判断集合中是否包含某个元素

 boolean remove(Object o): 删除集合中某个元素

 int size(): 获取集合中元素的个数

 Object[] toArray(): 将集合转换成数组

 

 1 import java.util.*; 2  3 public class CollectionDemo { 4   public static void main(String[] args) { 5  6     // 创建集合 7     Collection c = new ArrayList();// 多态 8  9     // 添加元素10     c.add(100); // 自动装箱11     c.add("Java编程");12 13     Person p = new Person("Bill", 21);14     c.add(p);// Collection集合只能单个存储元素,并且只能存储引用类型15 16     // 获取元素个数17     System.out.println(c.isEmpty());// false 说明集合c不为空18     System.out.println("c集合的元素个数为:" + c.size());// 个数为319 20     // 将集合转换成Object类型的数组21     Object[] obj = c.toArray();22     for (int i = 0; i < obj.length; i++) {23 24       // 输出结果:100 Java编程 Person[name=Bill,age=21]25       System.out.println(obj[i]);26     }27 28     // 删除指定元素29     c.remove(100); // 元素100已删30     System.out.println("c集合的元素个数为:" + c.size());// 个数为231 32     // 清空33     c.clear();34     System.out.println(c.isEmpty());// true 说明集合c为空35     System.out.println("c集合的元素个数为:" + c.size());// 个数为036 37   }38 }39 40 class Person {41   String name;42   int age;43 44   Person(String name, int age) {45     this.name = name;46     this.age = age;47   }48 49   // 重写Object中的toString方法50   public String toString() {51     return "Person[name=" + name + ",age=" + age + "]";52   }53 54 }

View Code

 

Iterator iterator();获取集合所依赖的迭代器对象

 通过迭代器中的方法完成集合的迭代(遍历)

 这种方式是所有集合通用的遍历方式  

Itertor接口定义的三个方法:

 boolean hasNext():如果仍有元素可以迭代,则返回 true。

 Object next(): 返回迭代的下一个元素。

 void remove(): 从迭代器指向的 collection 中移除迭代器返回的最后一个元素(可选操作)。

 Iterator必须依附于Collection对象,若有一个Iterator对象,则必然有一个与之关联的Collection对象。

当使用Iterator对集合元素进行迭代时,Iterator并不是把集合元素本身传给迭代变量,而是把集合元素的值传给迭代变量,因此当修改迭代变量的值时对集合元素本身没有任何影响  

注意:  当使用Iterator迭代访问Collection集合元素时,Collection集合里的元素不能被改变,只能通过Iterator的remove方法删除上一次next方法返回的集合元素,否则将会引发 java.util.CencurrentModificationException异常。

 

 1 import java.util.*; 2 public class IteratorDemo { 3  4   public static void main(String[] args) { 5  6     // 创建一个集合 7     Collection books = new HashSet(); 8     books.add("三国演义"); 9     books.add("西游记");10     books.add("水浒传");11 12     // 获取books集合对应的迭代器13     Iterator it = books.iterator();14     while (it.hasNext()) {15       // it.next()方法返回的是Object类型,需强制类型转换16       String str = (String) it.next();17       System.out.println(str);18 19       if (str.equals("三国演义")) {20         // 从集合中删除上一次next方法返回的元素21         it.remove();// 通过迭代器删除22 23         // 不要使用集合自身所带的remove方法,会引发异常24         // books.remove(str);25       }26       // 对str变量赋值,不会改变集合元素本身27       str = "红楼梦";// 此处代码对集合没有任何影响28     }29     System.out.println(books);// [西游记, 水浒传]30   }31 }

View Code

 

boolean contains(Object o):判断集合中是否包含某个元素
存储在集合中的元素应该重写equals方法

 1 import java.util.*; 2 public class ContainsDemo { 3  4   public static void main(String[] args) { 5  6     // 创建集合 7     Collection c = new ArrayList(); 8  9     // 创建Integer类型对象10     Integer i1 = new Integer(100);11 12     // 添加元素13     c.add(i1);14 15     // 判断集合中是否包含i116     System.out.println(c.contains(i1));// true17 18     // 创建另一个Integer类型对象19     Integer i2 = new Integer(100);20     // contains方法底层调用的是equals方法。Integer重写了equals方法,i1就是i221     System.out.println(c.contains(i2));// true22 23     // 创建一个Student对象24     Student s1 = new Student(100, "Bill");25     // 添加到集合里26     c.add(s1);27     // 判断集合c中是否包含s128     System.out.println(c.contains(s1));// true29 30     // 创建另一个Student对象31     Student s2 = new Student(100, "Bill");32     // 重写equals方法之前,比较的是内存33     // System.out.println(c.contains(s2));//false34 35     // 重写equals方法之后,比较的是内容36     System.out.println(c.contains(s2));// true37   }38 }39 40 class Student {41   int no;42   String name;43 44   Student(int no, String name) {45     this.no = no;46     this.name = name;47   }48 49   // 重写equals方法50   // 要求:编号和姓名相同则表示同一个Student51   public boolean equals(Object o) {52     if (this == o) {53       return true;54     }55     if (o instanceof Student) {56       Student s = (Student) o;57       if (s.no == this.no && s.name == this.name) {58         return true;59       }60     }61     return false;62   }63 }

View Code

List集合

 ArrayList集合底层是数组。数组是有下标的.  所以ArrayList集合有很多自己的特性.

 ArrayList集合底层默认初始化容量是 10. 扩大之后的容量是原容量的1.5倍.

 Vector集合底层默认初始化容量也是10.扩大之后的容量是原容量的2倍.

 如何优化ArrayList和Vector?  

尽量减少扩容操作,因为扩容需要数组拷贝。数组拷贝很耗内存。一般推荐在创建集合的时候指定初始化容量。

 1 import java.util.*; 2 public class ListDemo { 3  4   public static void main(String[] args) { 5  6     // 创建List集合 7     List li = new ArrayList(); 8     // List li = new LinkedList(); 9 10     // 添加元素11     li.add(100);12     li.add(200);13     li.add(400);14 15     // 在下标为2的位置上添加30016     li.add(2, 300);17 18     // 取得第一个元素19     System.out.println(li.get(0));// 10020 21     // 遍历(List集合特有的遍历方式)22     for (int i = 0; i < li.size(); i++) {23       Object o = li.get(i);24       System.out.println(o);25     }26 27     // 迭代器也可以28     Iterator it = li.iterator();29     while (it.hasNext()) {30       System.out.println(it.next());31     }32   }33 }

View Code

Set集合:HashSet

 1.HashSet底层实际上是一个HashMap,HashMap底层采用了哈希表数据结构。

 2.哈希表又叫做散列表,哈希表底层是一个数组,这个数组中每一个元素是一个单向链表。每个单向链表都有一个独一无二的hash值,代表数组的下标。在某个单向链表中的每一个节点上的hash值是相等的。hash值实际上是key调用hashCode方法,在通过"hash function"转换成的值。

 3.如何向哈希表中添加元素:先调用被存储的key的hashCode方法,经过某个算法得出hash值,如果在这个哈希表中不存在这个 hash值,则直接加入元素。如果该hash值已经存在,继续调用key之间的equals方法,如果equals方法返回false,则将该元素添加。如果equals方法返回true,则放弃添加该元素。

 4.HashSet其实是HashMap中的key部分。HashSet有什么特点,HashMap中的key 应该具有相同的特点。

 5.HashMap和HashSet初始化容量都是 16,默认加载因子是0.75,即当存储容量达到75%时就扩容。

 6.关于往Set集合中存储的元素,该元素的hashCode和equals方法:

 HashMap中有一个put方法,put(key,value) key是无序不可重复的.

 结论:存储在HashSet集合或者HashMap集合key部分的元素,需要同时重写hashCode+equals

 1 import java.util.*; 2 public class SetDemo { 3  4   public static void main(String[] args) { 5      6     // Set集合存储元素是无序不可重复的,这里就不做测试了 7      8     //创建集合 9     Set s = new HashSet();10     11     //这里假设键值重复只为做测试,实际上是不可重复的12     Employee e1 = new Employee("1000","JACK");13     Employee e2 = new Employee("1000","JACK");14     Employee e3 = new Employee("1000","SCOTT");15     Employee e4 = new Employee("2001","SUN");16     Employee e5 = new Employee("3000","JIM");17     Employee e6 = new Employee("3001","COOK");18     19     System.out.println(e1.hashCode());//重写hashCode方法后e1就是e220     System.out.println(e2.hashCode());21     22     //添加元素23     s.add(e1);24     s.add(e2);25     s.add(e3);26     s.add(e4);27     s.add(e5);28     s.add(e6);29     30     //查看集合元素个数31     System.out.println(s.size()); //532     33   }34 }35 36 //假设该公司员工编号是: 1000 - 999937 class Employee{38   39   //编号40   String no;41   42   //姓名43   String name;44   45   //Constructor46   Employee(String no,String name){47     this.no = no;48     this.name = name;49   }50   51   //重写equals方法.52   //如果员工编号相同,并且名字相同,则是同一个对象53   public boolean equals(Object o){54     if(this==o){55       return true;56     }57     if(o instanceof Employee){58       Employee e = (Employee)o;59       if(e.no.equals(this.no) && e.name.equals(this.name)){60         return true;61       }62     }63     64     return false;65   }66   67   //重写hashCode方法.68   public int hashCode(){69     //以员工编号分组.70     return no.hashCode();71   }72 }

View Code

 

先对SortedSet做测试

 1 import java.text.*; 2 import java.util.*; 3  4 public class SortedSetDemo01 { 5  6   public static void main(String[] args) throws Exception { 7  8     // 创建集合 9     SortedSet ss = new TreeSet();10 11     // 测试Integer类型12     ss.add(10); // 自动装箱13     ss.add(20);14     ss.add(15);15     ss.add(30);16     ss.add(25);17     ss.add(9);18 19     // 遍历20     Iterator it = ss.iterator();21     while (it.hasNext()) {22       Object element = it.next();23       System.out.println(element);//9 10 15 20 25 3024     }25 26     // 测试String类型27     SortedSet strs = new TreeSet();28 29     strs.add("JACK");30     strs.add("SUN");31     strs.add("KOOK");32     strs.add("LUCY");33     strs.add("KING");34 35     // 遍历36     it = strs.iterator();37     while (it.hasNext()) {38       Object element = it.next();39       System.out.println(element);40       /*输出:JACK41          KING42          KOOK43          LUCY44          SUN*/45     }46 47     // 测试日期Date类型48     String st1 = "2008-08-08";49     String st2 = "2009-08-08";50     String st3 = "2008-09-08";51     String st4 = "2008-08-09";52     String st5 = "2012-08-08";53 54     SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");55 56     Date t1 = sdf.parse(st1);57     Date t2 = sdf.parse(st2);58     Date t3 = sdf.parse(st3);59     Date t4 = sdf.parse(st4);60     Date t5 = sdf.parse(st5);61 62     // 添加63     SortedSet times = new TreeSet();64 65     times.add(t5);66     times.add(t2);67     times.add(t3);68     times.add(t4);69     times.add(t1);70 71     // 遍历72     it = times.iterator();73     while (it.hasNext()) {74       Object element = it.next();75       if (element instanceof Date) {76         Date d = (Date) element;77         78         System.out.println(sdf.format(d));79         /*输出:2008-08-0880             2008-08-0981            2008-09-0882            2009-08-0883            2012-08-08*/84       }85     }86   }87 }

View Code

SortedSet集合存储元素为什么可以自动排序?
  因为被存储的元素实现了Comparable接口,
      SUN编写TreeSet集合在添加元素的时候,会调用compareTo方法完成比较.

 1 import java.util.*; 2  3 public class SortedSetDemo02 { 4  5   public static void main(String[] args) { 6  7     SortedSet users = new TreeSet(); 8  9     User u1 = new User(15);10     User u2 = new User(16);11     User u3 = new User(25);12     User u4 = new User(13);13     User u5 = new User(11);14 15     // 添加元素16     users.add(u1);17     users.add(u2);18     users.add(u3);19     users.add(u4);20     users.add(u5);21 22     // 遍历23     Iterator it = users.iterator();24     while (it.hasNext()) {25       //输出:User[age=11] User[age=13] User[age=15] User[age=16] User[age=25]26       System.out.println(it.next());27     }28   }29 30 }31 32 // 这是第一种方式.33 class User implements Comparable {34 35   int age;36 37   User(int age) {38     this.age = age;39   }40 41   public String toString() {42     return "User[age=" + age + "]";43   }44 45   // 实现java.lang.Comparable;接口中的compareTo方法46   // 该方法程序员负责实现,SUN提供的程序已经调用了该方法.47   // 需求:按照User的age排序48   public int compareTo(Object o) {49     // 编写一个比较规则.50     int age1 = this.age;51     int age2 = ((User) o).age;52     return age1 - age2;53   }54 }

View Code

让SortedSet集合做到排序还有另一种方式:java.util.Comparator;

单独编写一个比较器.

 1 import java.util.*; 2  3 public class SortedSetDemo03 { 4  5   public static void main(String[] args) { 6  7     // 创建TreeSet集合的时候提供一个比较器. 8     SortedSet products = new TreeSet(new ProductComparator()); 9 10     // 匿名内部类:不推荐使用,因为比较器无法得到重复利用。11     /*12      * SortedSet products = new TreeSet(new Comparator() { // 需求:按照商品价格排序13      * public int compare(Object o1, Object o2) {14      * 15      * double price1 = ((Product) o1).price; double price2 = ((Product)16      * o2).price;17      * 18      * if (price1 == price2) { return 0; } else if (price1 > price2) {19      * return 1; } else { return -1; } } });20     */21 22     Product p1 = new Product(3.4);23     Product p2 = new Product(4.0);24     Product p3 = new Product(3.0);25     Product p4 = new Product(2.0);26     Product p5 = new Product(5.0);27 28     // 添加元素29     products.add(p1);30     products.add(p2);31     products.add(p3);32     products.add(p4);33     products.add(p5);34 35     // 遍历36     Iterator it = products.iterator();37     while (it.hasNext()) {38       //输出2.0 3.0 3.4 4.0 5.039       System.out.println(it.next());40       41     }42   }43 44 }45 46 class Product {47 48   double price;49 50   Product(double price) {51     this.price = price;52   }53 54   public String toString() {55     return price + "";56   }57 58 }59 60 // 第二种方法单独编写一个比较器61 62 class ProductComparator implements Comparator {63 64   // 需求:按照商品价格排序65   public int compare(Object o1, Object o2) {66 67     double price1 = ((Product) o1).price;68     double price2 = ((Product) o2).price;69 70     if (price1 == price2) {71       return 0;72     } else if (price1 > price2) {73       return 1;74     } else {75       return -1;76     }77   }78 79 }

View Code

 

下面是集合继承结构图-Map部分,从图中可以清楚的知道Map接口下子接口与实现类的关系。

关于Map集合中常用的方法


 void clear(); 清空Map
 boolean isEmpty();判断该集合是否为空
 int size(); 获取Map中键值对的个数。
 
 Object put(Object key, Object value); 向集合中添加键值对
 Object get(Object key);通过key获取value
 
  boolean containsKey(Object key); 判断Map中是否包含这样的key
  boolean containsValue(Object value); 判断Map中是否包含这样的value
  
  Object remove(Object key); 通过key将键值对删除.
  
  Collection values(); 获取Map集合中所有的value
  
  Set keySet(); 获取Map中所有的key
  
  Set entrySet();返回此映射中包含的映射关系的 Set 视图。

  注意:存储在Map集合key部分的元素需要同时重写hashCode+equals方法.

 1 import java.util.*; 2  3 public class MapDemo01{ 4    5   public static void main(String[] args){ 6      7     //1.创建Map集合 8     Map persons = new HashMap(); //HashMap的默认初始化容量是16,默认加载因子是0.75 9     10     //2.存储键值对11     persons.put("10000","JACK");12     persons.put("10011","JACK");13     persons.put("10002","SUN");14     persons.put("10003","COOK");15     persons.put("10004","KING");16     persons.put("10000","LUCY");17     18     //3.判断键值对的个数19     //Map中的key是无序不可重复的.和HashSet相同.20     System.out.println(persons.size());//521     22     //4.判断集合中是否包含这样的key23     System.out.println(persons.containsKey("10000")); //true24     25     //5.判断集合中是否包含这样的value26     //注意:Map中如果key重复了,value采用的是“覆盖”。27     System.out.println(persons.containsValue("LUCY")); //true28     29     //6.通过key获取value30     String k = "10002";31     Object v = persons.get(k);32     System.out.println(v); //SUN33     34     //7.通过key删除键值对35     persons.remove("10002");36     System.out.println(persons.size()); //437     38     //8.获取所有的value39     Collection values = persons.values();40     Iterator it = values.iterator();41     while(it.hasNext()){42       System.out.println(it.next()); 43       /*LUCY44        JACK45        COOK46        KING*/47     }48     49     //9.获取所有的key50     //以下程序演示如何遍历Map集合.51     Set keys = persons.keySet();52     53     Iterator it2 = keys.iterator();54     55     while(it2.hasNext()){56       Object id = it2.next();57       Object name = persons.get(id);58       System.out.println(id+"-->"+name);59       /*10000-->LUCY60       10011-->JACK61       10003-->COOK62       10004-->KING*/63 64     }65     66     //10.entrySet67     //将Map转换成Set集合.68     /*69     Set entrySet = persons.entrySet();70     Iterator it3 = entrySet.iterator();71     while(it3.hasNext()){72       System.out.println(it3.next());73     }74     */75     76   }77 }

View Code

 

使用集合的技巧:

看到Array就是数组结构,有角标,查询速度很快。

看到link就是链表结构:增删速度快,而且有特有方法。addFirst; addLast; removeFirst(); removeLast(); getFirst();getLast();

看到hash就是哈希表,就要想要哈希值,就要想到唯一性,就要想到存入到该结构的中的元素必须覆盖hashCode,equals方法。

看到tree就是二叉树,就要想到排序,就想要用到比较。

比较的两种方式:

一个是Comparable:覆盖compareTo方法;

一个是Comparator:覆盖compare方法。

LinkedHashSet,LinkedHashMap:这两个集合可以保证哈希表有存入顺序和取出顺序一致,保证哈希表有序。

 

   这是我在自学到java集合时通过看视频所整理出来的一部分内容,马马虎虎。在此感谢授课老师将视频分享,让在黑暗中摸索的我看到了一丝光明。把自己学到的一些知识分享出来是快乐的,这样也能鞭策自己,磨砺自己。所谓当局者迷,旁观者清,在此还望各位前辈不吝赐教,指出不足之处,这样我也才能更好的认清自己。下面附上我所看视频的下载地址:http://pan.baidu.com/s/1i342Y6x