黑马程序员----集合概述以及一些基本的方法应用

来源:互联网 发布:软件实施项目管理制度 编辑:程序博客网 时间:2024/04/27 19:01

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

集合:
之前存储大量对象引用使用数组:

 对象数组的弊端:
对于数组,定义时经常要使用长度信息,而大部分我们不会先期知道具体的数量。
 当数组一旦初始化后,其长度是不可变的
所以这个时候,Java就提供了另外一种强大容器:集合。
数组和集合的区别?
 A:长度区别

                            数组的长度固定
                            集合长度可变
                   B:内容不同
                            数组存储的是同一种类型的元素
                            而集合可以存储不同类型的元素
                   C:元素的数据类型问题
                            数组可以存储基本数据类型,也可以存储引用数据类型
                        集合只能存储引用类型

Collection:是集合的顶层接口,它的子体系有重复的,有唯一的,有有序的,有无序的。
List集合及其子类的特点:
  有序(存储和取出的元素一致),可重复的。
       ArrayList:
              底层数据结构是数组,查询快,增删慢。
              线程不安全,效率高。

       Vector:
              底层数据结构是数组,查询快,增删慢。
              线程安全,效率低。
       LinkedList:
              底层数据结构是链表,查询慢,增删快。
              线程不安全,效率高。
Set集合的特点:
无序(存储顺序和取出顺序不一致),唯一
HashSet保证元素唯一性:它的底层数据结构是哈希表结构:依赖hashCod()和equals()方法;所以在我们存储自定义对象时,如果你认为对象的成员变量值相同即为同一个对象的话,你就应该重写这两个方法。

LinkedHashSet:底层数据结构由哈希表和链表组成。
      哈希表保证元素的唯一性。
      链表保证元素有序。(存储和取出是一致)
TreeSet:能够对元素按照某种规则进行排序。
        排序有两种方式
               A:自然排序
               B:比较器排序
 TreeSet集合的特点:排序和唯一

 
Collection的功能概述:
1:添加功能
             boolean add(Object obj):添加一个元素
             boolean addAll(Collection c):添加一个集合的元素
  2:删除功能
             void clear():移除所有元素
             boolean remove(Object o):移除一个元素
             boolean removeAll(Collection c):移除指定集合的元素
  3:判断功能

             boolean contains(Object o):判断集合中是否包含指定的元素
             boolean containsAll(Collection c):判断集合中是否包含指定的集合元素                        boolean isEmpty():判断集合是否为空
  4:获取功能
             Iterator<E> iterator()(重点)
  5:长度功能
             int size():元素的个数
             面试题:数组有没有length()方法呢?字符串有没有length()方法呢?集合有没有length()方法呢?

      6:交集功能
boolean retainAll(Collectionc):移除当前集合未包含在指定集合中的元素,如果发生移除就返回true,否则返回false。
      7:把集合转换为数组
             Object[] toArray()
集合的遍历:
方式一:我们知道了集合有一个方法:Object[]  toArray();
       那么我们可不可以把集合转换成数组,然后再遍历数组呢?
Collectionc = new ArrayList();
Object[]objs = c.toArray();
for(inti=0;i<obj.length;i++){
System.out.println(obj[i]);//这里从Object[]数组中取出的元素,类型是Object的
}
当我们存储自定义对象时如何遍历呢?

例如:我们存储学生对象:(假设学生对象已经定义好了,并且有带参的构造方法)
Student stu=newStudent(“张三”,20);
Collectionc = new ArrayList();
c.add(stu);
Object[]objs = c.toArray();
for(inti=0;i<obj.length;i++){
System.out.println(obj[i]);//那么在这打印出来的就是学生对象的地址。这不是// 我们想要的
Students=(Student) obj[i];//这个时候需要向下转型,才能调用学生对象的方法

System.out.println(s.getName()+s.getAge);
}
方式二:Iterator iterator():迭代器,集合的专用遍历方式
      Object next():获取元素,并移动到下一个位置。
      NoSuchElementException:没有这样的元素,因为你已经找到最后了。
      boolean hasNext():如果仍有元素可以迭代,则返回 true。
在我们使用迭代器遍历的时候,Object next()无法知道是否是最后一个元素,所以我们在遍历的时候就需要作一下判断,所以使用hasNext(),做出判断然后再获取。
       Iteratorit=c.iterator();
       while(it.hasNext()){
       it.next();//它返回的仍然是Object类型;遍历自定义对象时仍需要向下转型
}
//for循环改写 : 别人用这种方式。自己要能看得懂
              for( Iteratorit = c.iterator() ;   it.hasNext()  ;  ){
                     Student s = (Student) it.next();
                    System.out.println(s.getName()+ "---" + s.getAge());
               }
List集合的特点:
  有序(存储和取出的元素一致),可重复的。
List集合的特有功能:
  A:添加功能
             void add(int index,Object element):在指定位置添加元素
  B:获取功能
              Objectget(int index):获取指定位置的元素
  C:列表迭代器         
ListIterator  listIterator():List集合特有的迭代器
  D:删除功能
              Objectremove(int index):根据索引删除元素,返回被删除的元素
  E:修改功能
              Objectset(int index,Object element):根据索引修改元素
List集合的遍历:除了使用Collection的方式还有:
        size()和get()方法结合:
                     for(inti=0;i<list.size();i++){
                            Objectobj=list.get(i);
}
ListIterator  listiterator()是List集合特有的迭代器,该迭代器继承了Iterator迭代器,所以,就可以直接使用hasNext()和next()方法。
Object previous():获取上一个元素
boolean hasPrevious():判断是否有元素
注意:ListIterator可以实现逆向遍历,但是必须先正向遍历,才能逆向遍历,所以一般无意义,不使用。
注意:使用迭代器在集合遍历的同时,想添加元素,这时候会抛出并发修改异常!
List:(面试题List的子类特点)
      ArrayList:
           底层数据结构是数组,查询快,增删慢。
           线程不安全,效率高。
      Vector:
           底层数据结构是数组,查询快,增删慢。
           线程安全,效率低。
      LinkedList:
           底层数据结构是链表,查询慢,增删快。
           线程不安全,效率高。
ArrayList:继承自List,有序的,可以存储重复元素
       存储自定义对象时:如果两个对象含有相同的属性那我们就认为这两个对象时重复的,我们是不想存入的。那么如何处理呢?首先我要了解contain()是依赖于equals()方法的, 我们的自定义类中继承了Object类的equals(),如果我们不重写,那么contain()方法调用的就是父类的equals()方法,所以我们要在自定义对象中重写equals()方法

classDemo{public static void main(String[] args){//实例化一个集合ArrayList list=new ArrayList();List.add(new Strudent(“张三”,20));List.add(new Strudent(“李四”,26));List.add(new Strudent(“王五”,25));List.add(new Strudent(“张三”,20));List.add(new Strudent(“周六”,27));//准备一个新集合,遍历原集合ArrayList list2=new ArrayList();for(int i=0;i<list.size();i++){if(!list2contain(list.get(i)){list2.add(list.get(i));}}//遍历新集合Iterator it=list2.iterator();while(it.hasNext()){Students=(Student)it.next();System.out.println(s.getName()+”---”+s.get.Age());}}}classStudent{String name;int age;public Student(String name;int age){this.name=name;this.age=age;}public String getName(){return name;}public int getName(){return age;}public booleanequals(Object obj) {if (this == obj)return true;if(obj == null)return false;if (getClass() !=obj.getClass())return false;Student other = (Student) obj;if (age != other.age)return false;if (name == null) {if (other.name != null)return false;} else if(!name.equals(other.name))return false;return true;}}


LinkedList:
特有功能:
              A:添加功能
                    public void addFirst(Objecte)
                    public void addLast(Object e)
             B:获取功能
                    public Object getFirst()
    public Obejct getLast()

     C:删除功能
                    public Object removeFirst()
                    public Object removeLast()
              因为它的特有功能,所以可以使用它模拟栈数据的集合存储
泛型:为什么会有泛型?
       我们知道一个集合里可以存储多种引用类型的数据,但是当我们遍历的时候却不能全部把它们当做一种类型来处理,这个时候我们就需要在一个集合中只存储一种类型,但是如何能保证呢?这时候泛型就给我们提供了这样的保证。

格式 <数据类型>
             此处的数据类型只能是引用类型。
好处: A:把运行时期的问题提前到了编译期间
             B:避免了强制类型转换
             C:优化了程序设计,解决了黄色警告线
泛型高级(通配符)
  ?:任意类型,如果没有明确,那么就是Object以及任意的Java类了
  ? extends E:向下限定,E及其子类
  ? super E:向上限定,E极其父类
JDK5的新特性:自动拆装箱,泛型,增强for,静态导入,可变参数,枚举
增强for:是for循环的一种。
      格式: for(元素数据类型 变量 : 数组或者Collection集合) {
                    使用变量即可,该变量就是元素
           }
  好处:简化了数组和集合的遍历。
变参数:定义方法的时候不知道该定义多少个参数
  格式:修饰符 返回值类型 方法名(数据类型 变量名){
             }

             注意:
                    这里的变量其实是一个数组
                    如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个
例如:public static void max(int n,int ... num){//可变参数编译后,就作为数组了
                            System.out.println("num = " +num);//数组地址
                            for(int x : num){
                            System.out.println(x);
                            }
                     }
 
Set集合的特点:
无序(存储顺序和取出顺序不一致),唯一
HashSet保证元素唯一性:它的底层数据结构是哈希表结构:依赖hashCod()和equals()方法;所以在我们存储自定义对象时,如果你认为对象的成员变量值相同即为同一个对象的话,你就应该重写这两个方法。
LinkedHashSet:底层数据结构由哈希表和链表组成。
      哈希表保证元素的唯一性。
      链表保证元素有序。(存储和取出是一致)
TreeSet:能够对元素按照某种规则进行排序。
      排序有两种方式
             A:自然排序
             B:比较器排序
 TreeSet集合的特点:排序和唯一
       TreeSet集合保证元素排序和唯一性的原理:
       唯一性:是根据比较的返回是否是0来决定。
        排序:
               A:底层数据结构是红黑树(是一个自平衡的二叉树)
              B:保证元素的排序方式
                     a:自然排序(元素具备比较性)
                            让元素所属的类实现Comparable接口
                            重写compareTo()方法
                            (如果compareTo()方法返回值是0,那么就认为是同一元素。)
                     b:比较器排序(集合具备比较性)
                            让集合构造方法接收一个比较器接口Comparator的子类对象  
Comparator是一个接口。那么我们需要自己定义一个它的实现类。
然后再把我们定义的比较器,通过TreeSet的带参构造方法传进去。
如果一个方法的参数是接口,那么真正要的是接口的实现类的对象而匿名内部类就可以实现这个东西
键盘录入5个学生信息(姓名,语文成绩,数学成绩,英语成绩),按照总分从高到低输出到控制台
分析:
       A:定义学生类
       B:创建一个TreeSet集合
       C:总分从高到底如何实现呢?            
       D:键盘录入5个学生信息
       E:遍历TreeSet集合

ClassStudent implements {       private String name;       private int Chinese;       private int math;       private int english;       publicStudent(String name, int chinese, int math, intenglish) {              super();              this.name =name;              this.chinese = chinese;               this.math =math;              this.english= english;       }       public Student() {              super();       }       public String getName() {              return name;       }       public voidsetName(String name) {              this.name =name;       }       public intgetChinese() {              return chinese;       }       public voidsetChinese(int chinese) {              this.chinese= chinese;       }       public intgetMath() {              return math;       }       public voidsetMath(int math) {              this.math =math;       }       public intgetEnglish() {              return english;       }       public voidsetEnglish(int english) {              this.english= english;       }       public intgetSum() {              return this.chinese + this.math + this.english;       }}public class TreeSetDemo {       public staticvoid main(String[] args) {              // 创建一个TreeSet集合              TreeSet<Student>ts = new TreeSet<Student>(new Comparator<Student>() {                     @Override                     public intcompare(Student s1, Student s2) {                            // 总分从高到低                            int num = s2.getSum() - s1.getSum();                            // 总分相同的不一定语文相同                            int num2 = num == 0 ? s1.getChinese() -s2.getChinese() : num;                            // 总分相同的不一定数序相同                            int num3 = num2 == 0 ? s1.getMath() -s2.getMath() : num2;                            // 总分相同的不一定英语相同                            int num4 = num3 == 0 ? s1.getEnglish() -s2.getEnglish() : num3;                            // 姓名还不一定相同呢                            int num5 = num4 == 0 ?s1.getName().compareTo(s2.getName())                                          :num4;                            return num5;                     }              });              System.out.println("学生信息录入开始");              // 键盘录入5个学生信息              for (intx = 1; x <= 5; x++) {                     Scannersc = new Scanner(System.in);                     System.out.println("请输入第" + x + "个学生的姓名:");                     Stringname = sc.nextLine();                     System.out.println("请输入第" + x + "个学生的语文成绩:");                     String chineseString =sc.nextLine();                     System.out.println("请输入第" + x + "个学生的数学成绩:");                     StringmathString = sc.nextLine();                     System.out.println("请输入第" + x + "个学生的英语成绩:");                     StringenglishString = sc.nextLine();                     // 把数据封装到学生对象中                     Students = new Student();                     s.setName(name);                     s.setChinese(Integer.parseInt(chineseString));                     s.setMath(Integer.parseInt(mathString));                     s.setEnglish(Integer.parseInt(englishString));                     // 把学生对象添加到集合                     ts.add(s);              }              System.out.println("学生信息录入完毕");              System.out.println("学习信息从高到低排序如下:");              System.out.println("姓名\t语文成绩\t数学成绩\t英语成绩");              // 遍历集合              for (Student s : ts) {                     System.out.println(s.getName() + "\t" + s.getChinese() + "\t"                                   +s.getMath() + "\t" +s.getEnglish()+"\t"+s.getSum());              }       }}


 

0 0