黑马程序员技术交流社区

标题: (主推)集合框架2:List与Set总结|Arrays|Collection与Collections [打印本页]

作者: 朱晓杰    时间: 2013-5-11 16:35
标题: (主推)集合框架2:List与Set总结|Arrays|Collection与Collections
本帖最后由 朱晓杰 于 2013-5-11 16:32 编辑

List和Set集合的总结|ArrayList与Vector|Collection与Collections |Arrays工具类|集合去重
1.List总结     
       List 接口是一个有序可重复集合,List集合默认按元素的添加顺序来设置元素的索引,可以通过索引来访问指定位置的元素(顺序索引从0开始)。List 接口继承Collection接口,实现了Collection的所有方法,凡是可操作角标的方法都是List特有的方法:

  1. import java.util.*;
  2. import static java.lang.System.*;
  3. class ListMethodDemo
  4. {
  5.         public static void main(String[] args)
  6.         {
  7.                 ArrayList list = new ArrayList();

  8.                 list.add("java01");
  9.                 list.add("java02");
  10.                 list.add("java03");
  11.                 list.add("java04");

  12.                 out.println("原集合:" + list);

  13.                 //在指定位置添加元素
  14.                 list.add(0,"java00");
  15.                 //如果索引超出范围 (index < 0 || index > size()),抛出IndexOutOfBoundsException
  16.                 //list.add(-1,"java-1");

  17.                 out.println("增加元素集合:" + list);

  18.                 //删除指定位置的元素
  19.                 list.remove(0);
  20.                 //如果索引超出范围 (index < 0 || index > size()),抛出IndexOutOfBoundsException
  21.                 //list.remove(-1,"java-1");

  22.                 out.println("删除元素集合:" + list);

  23.                 //修改元素
  24.                 list.set(0,"java");
  25.                 //如果索引超出范围 (index < 0 || index > size()),抛出IndexOutOfBoundsException
  26.                 //list.set(-1,"java");
  27.                
  28.                 out.println("修改元素集合:" + list);

  29.                 //获取所有元素
  30.                 ListIterator listit = list.listIterator();//列表迭代器
  31.                 while(listit.hasNext()){
  32.                         out.println(listit.next());
  33.                 }

  34.                 //通过indexOf获取对象位置,若元素不存在,返回-1
  35.                 out.println(list.indexOf("java"));

  36.                 //子列表,如果是非法的端点值 (fromIndex < 0 || toIndex > size || fromIndex > toIndex),抛出IndexOutOfBoundsException
  37.                 List sub = list.subList(0,10);
  38.                 out.println(sub);
  39.         }
  40. }
复制代码

List是接口,同时也拥有自己的具体实现类, ArrayList,LinkedList,Vector。
ArrayList
底层数据结构是数组结构,线程不安全,特点:查询速度很快
LinkedList
LinkedList底层数据结构是链表,线程不安全,特点是增删速度很快,查询速度稍慢。
LinkedList 类还为在列表的开头及结尾 get、remove 和 insert 元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列或双端队列。
此类实现 Deque 接口,为 add、poll 提供先进先出队列操作,以及其他堆栈和双端队列操作。
  1. /*
  2. 使用LinkedList模拟堆栈和队列
  3. 堆栈:先进后出(被子) FILO
  4. 队列:先进先出(水管) FIFO
  5. */
  6. import java.util.*;
  7. import static java.lang.System.*;
  8. class LinkedListDemo
  9. {
  10.         public static void main(String[] args)
  11.         {
  12.                 DuiLie dl = new DuiLie();
  13.                 dl.myAdd("java01");
  14.                 dl.myAdd("java02");
  15.                 dl.myAdd("java03");
  16.                 dl.myAdd("java04");
  17.                
  18.                 out.println("先进后出:");
  19.                 while(!dl.isNull()){
  20.                         out.println(dl.myGetFILO());
  21.                 }

  22.                 /*out.println("先进先出:");
  23.                 while(!dl.isNull()){
  24.                         out.println(dl.myGetFIFO());
  25.                 }*/
  26.         }
  27. }

  28. class DuiLie
  29. {
  30.         private LinkedList list;
  31.         
  32.         public DuiLie(){
  33.                 list = new LinkedList();
  34.         }

  35.         public void myAdd(Object obj){
  36.                 list.offerFirst(obj);
  37.         }

  38.         public Object myGetFIFO(){//先进先出
  39.                 return list.removeLast();
  40.         }

  41.         public Object myGetFILO(){//先进后出
  42.                 return list.removeFirst();
  43.         }

  44.         public boolean isNull(){
  45.                 return list.isEmpty();
  46.         }
  47. }
复制代码
Vector
底层数据结构是数组结构,线程安全,与Arraylist、LinkedList相比,操作效率低
关于使用List集合的几点建议:
•如果需要遍历List集合元素,对应ArrayList、Vector集合,则应该使用随机访问方法(get)来遍历集合元素,这样性能更好。对应LinkedList集合,则应采用迭代器(Iterator)来遍历集合元素。
•如果需要经常执行插入、删除操作来改变Lst集合大小,则应该使用LinkedList集合,而不是ArrayList。
•如果多条线程需要同时访问List集合中的元素,可以考虑使用Vector这个同步实现,或者考虑使用Collections工具类实现同步。

2.Set总结
Set接口继承Collection接口,是一个无序且不重复的集合。先说HashSet
HashSet
集合的底层结构是一个哈希表数据结构 ,无序(存进去和取出来的顺序可能不一致),不可以存入重复的元素,存入HashSet集合的元素需要覆盖hashCode()方法和equals()方法。
HashSet是如何保证元素的唯一性的呢?
是通过元素的两个方法 hashCode() 和equals()方法。
如果元素的hashCode()相同,才会判断equals是否为true;
如果元素的hashCode()不同,直接存入到HashSet集合,则不会调用equals方法。

HashSet对于判断元素是否存在,以及删除等操作,依赖的是也是hashCode和equals方法。
  1. import java.util.*;
  2. import static java.lang.System.*;
  3. /*
  4. HashSet是如何保证元素的唯一性的呢?
  5. 是通过元素的两个方法 hashCode() 和equals() 方法。
  6. 如果元素的hashCode()相同,才会判断equals是否为true;
  7. 如果元素的hashCode()不同,直接存入到HashSet集合,则不会调用equals方法。

  8. HashSet对于判断元素是否存在,以及删除等操作,依赖的是也是hashCode和equals方法。
  9. */
  10. class HashSetTest
  11. {
  12.         public static void main(String[] args)
  13.         {
  14.                 HashSet hs = new HashSet();

  15.                 hs.add(new Student("zhangsan",18));
  16.                 hs.add(new Student("zhangsan",18));
  17.                 hs.add(new Student("lisi",40));
  18.                 hs.add(new Student("lisi",40));
  19.                 hs.add(new Student("wangwu",20));
  20.                 hs.add(new Student("wangwu",20));

  21.                 Iterator it = hs.iterator();
  22.                 while(it.hasNext()){
  23.                         Student s = (Student)it.next();
  24.                         out.println("name=" + s.getName() + "...age=" + s.getAge());
  25.                 }
  26.         }
  27. }

  28. class Student//学生类
  29. {
  30.         private String name;//姓名
  31.         private int age;//年龄

  32.         Student(String name, int age){
  33.                 this.name = name;
  34.                 this.age = age;
  35.         }
  36.         
  37.         public int hashCode(){//覆写hashCode的方法,保证元素唯一性
  38.                 return name.hashCode() + age*28;
  39.         }

  40.         public boolean equals(Object obj){//覆写Object的equals方法
  41.                 if(!(obj instanceof Student))
  42.                         return false;
  43.                 Student s = (Student)obj;
  44.                 return this.name.equals(s.name) && this.age == s.age;
  45.         }

  46.         public String getName(){//获取学生姓名
  47.                 return this.name;
  48.         }

  49.         public int getAge(){//获取学生年龄
  50.                 return this.age;
  51.         }
  52. }
复制代码
再说TreeSet:
TreeSet底层的数据结构是二叉树数据结构  不可有重复元素,TreeSet集合取出是有序的 ,之所以有序是因为TreeSet有两种排序方式。
TreeSet排序的第一种方式:让存入TreeSeet集合的元素自身具备比较性。元素需要实现Comparable接口,覆盖CompareTo方法。
这种方式也称为元素的自然顺序。
ThreeSet的第二种排序方式。
当元素自然不具备比较性时,或者具备的比较性不是所需要的。
这时就需要让集合自身具备比较性。定义一个比较器类将比较器对象作为参数传递给TreeSet集合的构造函数。当两种排序方式都存在时,以比较器方式为主。



作者: 朱晓杰    时间: 2013-5-11 16:35
本帖最后由 朱晓杰 于 2013-5-11 16:34 编辑
  1. import java.util.*;
  2. import static java.lang.System.*;
  3. /*
  4. TreeSet有两种排序方式。
  5. 1.让存入TreeSeet集合的元素自身具备比较性。元素需要实现Comparable接口,覆盖CompareTo方法。这种方式也称为元素的自然顺序。
  6. 2.当元素自然不具备比较性时,或者具备的比较性不是所需要的。
  7. 这时就需要让集合自身具备比较性。定义一个比较器类将比较器对象作为参数传递给TreeSet集合的构造函数。
  8. 实现Comparator 接口,覆盖compare方法

  9. 当两种排序方式都存在时 ,以比较器方式为主。

  10. 如何保证元素的唯一性:
  11. compareTo()方法返回 0

  12. */
  13. class TreeSetTest
  14. {
  15.         public static void main(String[] args)
  16.         {
  17.                 /*第一种排序方式:自然排序,让集合自身具备比较性
  18.                 需求:存储学生对象,按照年龄排序,如果年龄相等按照姓名的顺序排序
  19.                 */
  20.                 TreeSet first = new TreeSet();

  21.                 first.add(new Student("zhangsan",19));
  22.                 first.add(new Student("zhangsan",19));
  23.                 first.add(new Student("lisi",18));
  24.                 first.add(new Student("wangwu",20));
  25.                 first.add(new Student("zhaoliu",19));
  26.                 out.println("第二种排序方式:");
  27.                 Iterator itFir = first.iterator();
  28.                 while(itFir.hasNext()){
  29.                         Student s = (Student)itFir.next();
  30.                         out.println("name=" + s.getName() + "...age=" + s.getAge());
  31.                 }

  32.                 /*第二种排序方式:让集合自身具备比较性*/
  33.                 TreeSet second = new TreeSet(new MyComp());

  34.                 second.add(new Student("zhangsan",19));
  35.                 second.add(new Student("zhangsan",16));
  36.                 second.add(new Student("lisi",18));
  37.                 second.add(new Student("wangwu",20));
  38.                 second.add(new Student("zhaoliu",17));
  39.                 out.println("第二种排序方式:");
  40.                 Iterator itSec = second.iterator();
  41.                 while(itSec.hasNext()){
  42.                         Student s = (Student)itSec.next();
  43.                         out.println("name=" + s.getName() + "...age=" + s.getAge());
  44.                 }
  45.         }
  46. }

  47. class Student implements Comparable//学生类,该接口强制是student具有比较性
  48. {
  49.         private String name;//姓名
  50.         private int age;//年龄

  51.         Student(String name, int age){
  52.                 this.name = name;
  53.                 this.age = age;
  54.         }
  55.        
  56.         public int compareTo(Object obj){//覆写compareTo方法,让元素自身具备比较性
  57.                 if(!(obj instanceof Student))
  58.                         throw new RuntimeException("类型不匹配,不是学生对象!");
  59.                 Student s = (Student)obj;
  60.                 int num = Integer.valueOf(this.age).compareTo(Integer.valueOf(s.age));
  61.                 if(num == 0){
  62.                         num = this.name.compareTo(s.name);
  63.                 }
  64.                 return num;
  65.         }

  66.         public String getName(){//获取学生姓名
  67.                 return this.name;
  68.         }

  69.         public int getAge(){//获取学生年龄
  70.                 return this.age;
  71.         }
  72. }

  73. class MyComp implements Comparator//自定义比较器
  74. {
  75.         public int compare(Object o1,Object o2){
  76.                 if(!(o1 instanceof Student || o2 instanceof Student))
  77.                         throw new RuntimeException("类型不匹配,不是学生对象!");
  78.                
  79.                 Student s1 = (Student)o1;
  80.                 Student s2 = (Student)o2;
  81.                
  82.                 int num = s1.getName().compareTo(s2.getName());
  83.                 if(num == 0){
  84.                         num = Integer.valueOf(s1.getAge()).compareTo(Integer.valueOf(s2.getAge()));
  85.                 }
  86.                 return num;
  87.         }
  88. }
复制代码
3.Collection与Collections
java.util.Collection 是一个集合接口。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式。
java.util.Collections 是一个包装类。它包含有各种有关集合操作的静态多态方法,是一个工具类,服务于Java的Collection框架。

4、Arrays工具类
用来操作数组(比如排序和搜索)的各种方法。此类还包含一个允许将数组作为列表来查看的静态工厂
常用方法总结:
数组转换成List集合,好处:可以使用集合的思想和方法来操作数组中的元素
注意:转换后的List不能使用增加和删除方法,因为数组长度固定
asList(T... a)
集合变数组
toArray()  好处:限定对集合中的元素进行操作
排序:
sort(Object[] a)
根据元素的自然顺序对指定对象数组按升序进行排序。

示例:
  1. /*
  2. Arrays用于操作数组的工具类。下面演示Arrays中常用方法。
  3. 数组变集合
  4. asList(T...a)
  5. 好处:可以使用集合的思想和方法来操作数组中的元素
  6. 注意:如果数组中的元素都是对象,那么变成集合时,数组中的元素直接变成集合中的元素
  7.           如果数组中的元素都是基本数据类型,那么变成集合时,会将该数组作为集合中的元素

  8. 集合变数组
  9. toArray();
  10. toArray(T[] t);
  11. 好处:限定了对集合的操作,不可增删

  12. 排序
  13. sort(Object[] a)
  14. 根据元素的自然顺序对指定对象数组按升序进行排序。
  15. */
  16. import java.util.*;
  17. import static java.lang.System.*;
  18. import static java.util.Arrays.*;
  19. class ArraysDemo
  20. {
  21.         public static void main(String[] args)
  22.         {
  23.                 //数组变结合
  24.                 String[] arr = {"aaa","bbb","ccc","ddd"};

  25.                 List<String> list = asList(arr);

  26.                 out.println(list);

  27.                 //Integer[] nums = {1,5,9};
  28.                 int[] nums = {1,5,9};

  29.                 List<int[]> numsList = asList(nums);

  30.                 out.println(numsList);
  31.                
  32.                 //集合变数组
  33.                 ArrayList<String> li = new ArrayList<String>();
  34.                 li.add("java01");
  35.                 li.add("java05");
  36.                 li.add("java03");

  37.                 String[] arrs = li.toArray(new String[li.size()]);
  38.                 out.println(Arrays.toString(arrs));

  39.                 //排序
  40.                 Arrays.sort(arrs);
  41.                 out.println(Arrays.toString(arrs));
  42.         }
  43. }
复制代码

作者: 朱晓杰    时间: 2013-5-11 16:40
尹桥印 发表于 2013-5-11 16:38
我又来看楼主总结了

今天不在状态啊,估计总结的不怎么样!压力确实有点儿大啊!
作者: Oyxiaoxi    时间: 2013-5-11 16:43
学习下吧…
作者: Miss小强    时间: 2013-5-11 17:03
我来补充一点:Set集合的底层实现原理是Map集合;即将Map的值无视他。
HashSet底层用的是HashMap,
TreeSet底层用的是TreeMap;
TreeSet和TreeMap判断元素唯一性和顺序依赖的是compareTo方法的返回值或者指定比较器的比较方法的返回值;
集合和数组进行互相转换的时候有限制:
  int[] arr=new int[]{34,56,7,9};
           List list= Arrays.asList(arr);
           list.remove(2);//出现java.lang.UnsupportedOperationException
作者: 朱晓杰    时间: 2013-5-11 17:24
Miss小强 发表于 2013-5-11 17:03
我来补充一点:Set集合的底层实现原理是Map集合;即将Map的值无视他。
HashSet底层用的是HashMap,
TreeSet ...

:handshake  3KU,后面加上!




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2