首页 > 学院 > 开发设计 > 正文

java基础——集合

2019-11-15 00:34:25
字体:
来源:转载
供稿:网友
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(); 清空Mapboolean isEmpty();判断该集合是否为空int size(); 获取Map中键值对的个数。 Object put(Object key, Object value); 向集合中添加键值对Object get(Object key);通过key获取value boolean containsKey(Object key); 判断Map中是否包含这样的keyboolean containsValue(Object value); 判断Map中是否包含这样的value Object remove(Object key); 通过key将键值对删除.Collection values(); 获取Map集合中所有的valueSet keySet(); 获取Map中所有的keySet 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


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表