集合与数组的区别:
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
新闻热点
疑难解答