标签:
集合与数组的区别:
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());// 个数为3 19 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());// 个数为2 31 32 // 清空 33 c.clear(); 34 System.out.println(c.isEmpty());// true 说明集合c为空 35 System.out.println("c集合的元素个数为:" + c.size());// 个数为0 36 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 }
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 }
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 // 判断集合中是否包含i1 16 System.out.println(c.contains(i1));// true 17 18 // 创建另一个Integer类型对象 19 Integer i2 = new Integer(100); 20 // contains方法底层调用的是equals方法。Integer重写了equals方法,i1就是i2 21 System.out.println(c.contains(i2));// true 22 23 // 创建一个Student对象 24 Student s1 = new Student(100, "Bill"); 25 // 添加到集合里 26 c.add(s1); 27 // 判断集合c中是否包含s1 28 System.out.println(c.contains(s1));// true 29 30 // 创建另一个Student对象 31 Student s2 = new Student(100, "Bill"); 32 // 重写equals方法之前,比较的是内存 33 // System.out.println(c.contains(s2));//false 34 35 // 重写equals方法之后,比较的是内容 36 System.out.println(c.contains(s2));// true 37 } 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 // 要求:编号和姓名相同则表示同一个Student 51 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 }
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的位置上添加300 16 li.add(2, 300); 17 18 // 取得第一个元素 19 System.out.println(li.get(0));// 100 20 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 }
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就是e2 20 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()); //5 32 33 } 34 } 35 36 //假设该公司员工编号是: 1000 - 9999 37 class Employee{ 38 39 //编号 40 String no; 41 42 //姓名 43 String name; 44 45 //Constructor 46 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 }
先对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 30 24 } 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 /*输出:JACK 41 KING 42 KOOK 43 LUCY 44 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-08 80 2008-08-09 81 2008-09-08 82 2009-08-08 83 2012-08-08*/ 84 } 85 } 86 } 87 }
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 }
让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.0 39 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 }
下面是集合继承结构图-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());//5 21 22 //4.判断集合中是否包含这样的key 23 System.out.println(persons.containsKey("10000")); //true 24 25 //5.判断集合中是否包含这样的value 26 //注意:Map中如果key重复了,value采用的是“覆盖”。 27 System.out.println(persons.containsValue("LUCY")); //true 28 29 //6.通过key获取value 30 String k = "10002"; 31 Object v = persons.get(k); 32 System.out.println(v); //SUN 33 34 //7.通过key删除键值对 35 persons.remove("10002"); 36 System.out.println(persons.size()); //4 37 38 //8.获取所有的value 39 Collection values = persons.values(); 40 Iterator it = values.iterator(); 41 while(it.hasNext()){ 42 System.out.println(it.next()); 43 /*LUCY 44 JACK 45 COOK 46 KING*/ 47 } 48 49 //9.获取所有的key 50 //以下程序演示如何遍历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-->LUCY 60 10011-->JACK 61 10003-->COOK 62 10004-->KING*/ 63 64 } 65 66 //10.entrySet 67 //将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 }
使用集合的技巧:
看到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
标签:
原文地址:http://www.cnblogs.com/zhimu/p/4563205.html