zoukankan      html  css  js  c++  java
  • Java类集框架

      类集实际上就属于动态对象数组,那么在实际的开发之中数组的概念出现的几率并不高,99%情况下使用的都是一维数组,并且99%的操作都只是进行简单的for循环处理,但是必须清楚数组本身有一个最大的缺陷:数组的长度是固定的 就是因为此问题的存在,所以才开发出了链表,但是对于链表的实现非常的困难,对于之前写的链表使用的是Object,那么就有一个潜在的问题了:如果设置的数据类型不一样,那么就会操作ClassCastException(取数据的时候会比较方法)

      从JDK1.2开始为了解决数组的长度问题,专门提供了动态数组实现框架---java类集框架,所谓的类集的开发框架就是java针对于数据结构的一种实现,而在数据结构之中,最为基础的数据结构就是链表。

    回顾:链表的特点

      这种节点关系的处理操作,核心就需要一个Node类(保存数据,设置数据)

      在进行链表数据查找.删除的时候需要equals()方法支持:

      在实际的开发之中对于这些数据结构的使用都有一些共性的特点:存进去,取出来

      对于以上给出的链表操作方法,在类集里面还会见到。所以讲解的时候请千万不要忽悠了分析的原理。

    Collection集合接口

      在Java的类集里面(java.util包)提供有两个最为核心的操作接口:Collection Map接口,其中Collection的接口操作与之前链表的操作形式类似,每一次进行数据操作的时候只能够对单个对象进行处理。

      所以Collection是单个集合保存的最大父接口。Collection接口定义如下:public interface Collection<E> extends Iterable<E>

      从JDK1.5开始发现Collection接口上追加有泛型引用,这样的直接好处就是可以避免了ClassCastException里面所有的数据保存类型应该想用的。在JDK1.5之前Iterable()方法是直接在Collection接口里定义的,对于此类的常用方法有如下几个:

      向集合中添加数据:public boolean add(E e)

      向集合中添加一组数据:public boolean addAll(Collection<? extends E> c)

      清空数据:public void clear() 

      查找数据是否存在,需要使用equals:boolean contains(Object o)

      删除数据,需要euqas方法:boolean remove(Object o)

      取得集合长度:int size()

      将集合变为对象数组返回:Object[] toArray()

      取得Iterator对象用于输出:Iterator<E> iterator()

      在开发中使用比率来讲:add() iterator()两个方法占到了95%以上,其他方法基本用不上。但是需要实际开发中很少会直接使用Collection接口(18年前,使用最多一定是Collection接口),因为Collection接口只是一个存取数据的标准,而并不是区分存储的类型,例如:如果要存放数据可能需要区分重复与不重复。所以在实际的开发之中,往往会去考虑使用Collection接口的子接口:List(允许重复) Set(不允许重复)

      Collection接口中有两个重要的方法:add() iteractor() 子接口都有这个方法,

    List的集合接口

      在实际的开发过程中,List集合接口的使用比率的可以达到Collection系列的80%,在进行集合处理的时候优先考虑的一定是List集合接口,首先观察一下Lsit接口中提供的方法,在这个接口里面有连个扩充方法

      根据索引取得数据保存数据:E get(int index)

      修改数据:E set(int index,E element)

    List接口与Collection接口相比最大的特点在于其有一个get()方法,可以根据索引取得内容,但是List本身还属于一个接口,而如果要取得接口的实例化对象,就必须有子类,在我们List的接口下有三个常用子类:Array Vector LinkedList 

      最终的操作还是以接口为主,所以所有的方法只参考接口的定义即可。

    ArrayList(90%)

      ArrayList是一个针对List接口的数组操作实现,那么下面首先利用ArrayList做一些List基本操作。

    范例:观察List基本处理

     1 package cn.Tony.demo;
     2 
     3 import java.util.ArrayList;
     4 import java.util.List;
     5 
     6 public class TestDemo{
     7     public static void main(String[] args) throws Exception {
     8         List<String> all=new ArrayList<String>();
     9         all.add("Hello");
    10         all.add("Hello");//重复数据
    11         all.add("World");
    12         System.out.println(all);
    13     }
    14 } 

      通过此时的观察可以得到证实,咋们的List允许保存重复的数据的

     1 package cn.Tony.demo;
     2 
     3 import java.util.ArrayList;
     4 import java.util.List;
     5 
     6 public class TestDemo{
     7     public static void main(String[] args) throws Exception {
     8         List<String> all=new ArrayList<String>();
     9         System.out.println(all.size()+","+all.isEmpty());
    10         all.add("Hello");
    11         all.add("Hello");//重复数据
    12         all.add("World");
    13         all.remove("Hello");
    14         System.out.println(all.size()+","+all.isEmpty());
    15         System.out.println(all.contains("AbC"));
    16         System.out.println(all.contains("World"));
    17         System.out.println(all);
    18     }
    19 } 

      List本身有一个好的支持:它存在一个get()方法,那么利用get()方法利用索引取出数据。

    范例:观察List的get()操作

     1 package cn.Tony.demo;
     2 
     3 import java.util.ArrayList;
     4 import java.util.List;
     5 
     6 public class TestDemo{
     7     public static void main(String[] args) throws Exception {
     8         List<String> all=new ArrayList<String>();
     9         all.add("Hello");
    10         all.add("Hello");//重复数据
    11         all.add("World");
    12         for(int x=0;x<all.size();x++) {
    13             System.out.println(all.get(x));
    14         }
    15     }
    16 } 

      但是千万要记住get()是List子接口的。如果你现在使用的不是List而是Collection(虽然这种情况大多数不会发生)那么对于此时的数据取出

    你只能讲集合变为对象数组来操作了。

    范例:通过Collection进行输出处理

     1 package cn.Tony.demo;
     2 
     3 import java.util.ArrayList;
     4 import java.util.Arrays;
     5 import java.util.Collection;
     6 
     7 public class TestDemo{
     8     public static void main(String[] args) throws Exception {
     9         Collection<String> all=new ArrayList<String>();
    10         all.add("Hello");
    11         all.add("Hello");//重复数据
    12         all.add("World");
    13         //操作以Object形式返回,那么就有可能需要进行向下转型。那么就有可能操作ClassCastException安全隐患
    14         Object[] result=all.toArray();//变为Object对象数组
    15         System.out.println(Arrays.toString(result));
    16     }
    17 } 

      此类操作在开发中尽量回避,你们所写的代码,不到万不得已(一般不会出现)不要使用Collection

    集合与简单Java类

      在实际的开发之中,集合里面保存最多的数据类型,就是简单java类,所以下面针对于简单java类的集合操作做一个说明。

    范例:先向集合保存简单java类

     1 package cn.Tony.demo;
     2 
     3 import java.util.ArrayList;
     4 import java.util.List;
     5 
     6 class Person{
     7     private String name;
     8     private Integer age;
     9     public Person(String name,Integer age){
    10         this.name=name;
    11         this.age=age;
    12     }
    13     @Override
    14     public boolean equals(Object obj) {
    15         if(this==obj) {
    16             return true;
    17         }
    18         if(this==null) {
    19             return false;
    20         }
    21         if(!(obj instanceof Person)) {
    22             return false;
    23         }
    24         Person per=(Person)obj;//这个可以向下转型
    25         return this.name.equals(per.name)&&this.age.equals(per.age);
    26     }
    27     @Override
    28     public String toString() {
    29         return "Person [name=" + name + ", age=" + age + "]";
    30     }
    31 }
    32 public class TestDemo{
    33     public static void main(String[] args) throws Exception {
    34         List<Person> all=new ArrayList<Person>();
    35         all.add(new Person("张三",10));
    36         all.add(new Person("李于",11));
    37         all.add(new Person("挖宝",12));
    38         //对于集合中的remove() contains()方法必须类中有equals支持
    39         all.remove(new Person("李于",11));
    40         System.out.println(all.contains(new Person("李于",11)));
    41         for(int x=0;x<all.size();x++) {
    42             System.out.println(all.get(x));
    43         }
    44     }
    45 } 

      从何理论上讲contains() remove()需要equals()支持,但是实际上很多有人真去这么作,也就是说简单java类里面实现equal方法的几率在开发中出现的可能性是很低的。

    旧的子类:Vector(1%)

      Vecter这个类是JDK1.0的时候就提出了,而ArrayList是JDK1.2提出的。最初的java再开发类集的时候考虑将Vector取消了,因为这个了类的实现机制太古老了,可是后来又考虑有许多人已经习惯于使用Vector了,那么于是对于Vector进行了重新的设计。让其多实现看一个List接口。

    范例:使用Vector

     1 package cn.Tony.demo;
     2 
     3 import java.util.List;
     4 import java.util.Vector;
     5 
     6 public class TestDemo{
     7     public static void main(String[] args) throws Exception {
     8         List<String> all=new Vector<String>();
     9         all.add("Hello");
    10         all.add("Hello");
    11         all.add("World");
    12         all.remove("Hello");
    13         System.out.println(all);
    14     }
    15 } 

    面试题:请解释ArrayList和Vector的区别?

     

      在以后的使用过程中优先考虑ArrayList

     LinkedList子类(5%)

      在List接口里面还有一个LinkedList子类,这个子类如果向父接口转型的话,使用的形式和之前没有任何区别。

     1 package cn.Tony.demo;
     2 
     3 import java.util.LinkedList;
     4 import java.util.List;
     5 
     6 
     7 public class TestDemo{
     8     public static void main(String[] args) throws Exception {
     9         List<String> all=new LinkedList<String>();
    10         all.add("Hello");
    11         all.add("Hello");
    12         all.add("World");
    13         all.remove("Hello");
    14         System.out.println(all);
    15     }
    16 } 

    面试题:请解释ArrayList和LinkedList的区别?

      ArrayList封装的是一个数组,LinkedList封装的是一个链表实现,ArrayList时间复杂度为1 而LinkedList时间复杂度为n

    开发之中考虑的就是ArrayList如果考虑性能就要初始化大小

    Set集合接口

      Set接口与List最大的不同在于Set接口中的内容是不允许重复的,同时也需要注意一点,Set与List最大的不同在于:Set接口并没有对Collection接口进行扩充,而List对Collection进行了扩充,由于是JDK1.8的原因,所以在Collection接口里面提供有一些default方法,而这些方法并没有在Set接口出现,也就是Set接口面不可能有gfet方法处理的,而在Set子接口里面有两个常用的子类:HashSet TreeSet。

    范例:观察HashSet的使用 

     1 package cn.Tony.demo;
     2 
     3 import java.util.HashSet;
     4 import java.util.Set;
     5 
     6 public class TestDemo{
     7     public static void main(String[] args) throws Exception {
     8         Set<String> all=new HashSet<String>();
     9         all.add("Hello");
    10         all.add("Hello");//重复元素
    11         all.add("World");
    12         all.add("Tony");
    13         all.add("Java");
    14         System.out.println(all);
    15         
    16     }
    17 } 

    范例:观察TreeSet的使用

     1 package cn.Tony.demo;
     2 
     3 import java.util.Set;
     4 import java.util.TreeSet;
     5 
     6 public class TestDemo{
     7     public static void main(String[] args) throws Exception {
     8         Set<String> all=new TreeSet<String>();
     9         all.add("B");
    10         all.add("C");//重复元素
    11         all.add("D");
    12         all.add("A");
    13         all.add("E");
    14         System.out.println(all);
    15         
    16     }
    17 } 

      TreeSet使用的一个升序排序的!

    集合排序说明(TreeSet)

      既然TreeSet子类可以进行排序,所以下面编写一个自己的类希望可以通过TreeSet实现数据排序处理操作。此时如果要进行排序要进行对象数组的排序,在之前就已经明确说明了,对象所在的类一定要实现Comparable接口,而且compareTo()方法,因为只有通过此方法才能知道大小关系,

      但是需要提醒的是,如果你现在真实用了Comparable接口大小关系匹配的时候,你就需要当心自己给自己挖坑了,因为所有的属性必须全部比较参数,

    范例:使用TreeSet排列

     1 package cn.Tony.demo;
     2 
     3 import java.util.Set;
     4 import java.util.TreeSet;
     5 
     6 class Person implements Comparable<Person>{
     7     private String name;
     8     private Integer age;
     9     public Person(String name,Integer age) {
    10         this.name=name;
    11         this.age=age;
    12     }
    13     @Override
    14     public String toString() {
    15         return "Person [name=" + name + ", age=" + age + "]"+"
    ";
    16     }
    17     @Override
    18     public int compareTo(Person o) {
    19         if(this.age>o.age) {
    20             return 1;
    21         }else if(this.age<o.age) {
    22             return -1;
    23         }else {
    24             return this.name.compareTo(o.name);
    25         }
    26     }
    27 }
    28 
    29 public class TestDemo{
    30     public static void main(String[] args) throws Exception {
    31         Set<Person> set=new TreeSet<Person>();
    32         set.add(new Person("张三",20));
    33         set.add(new Person("张三",20));//重复数据
    34         set.add(new Person("李四",20));//年龄重复
    35         set.add(new Person("王五",19));
    36         System.out.println(set);
    37     }
    38 } 

      因为在实际的开发中TreeSet的使用实在是过于麻烦了,在项目的开发里面,简单Java类是根据数据表设计来的,如果一张表的字段暴多,你这个类得写死。

    重复元素判断

      在使用TreeSet的子类进行数据保存的时候,重复元素的判断依靠的是Comparable接口完成的。但是这并不是全部Set接口重复元素的方式,因为如果使用的是HashSet子类,由于其跟Comparable没有任何关系,所以他判断元素的方式就依靠Object类中的两个方法:

        hash码:public int hashCode()

        对象比较:public boolean equals(Object obj)

      在Java中进行对象比较的操作需要有两步:第一步要通过一个对象的唯一编码找到一个对象的信息,当编码匹配后在调用equals方法进行内容的比较。

     1 package cn.Tony.demo;
     2 
     3 import java.util.HashSet;
     4 import java.util.Set;
     5 
     6 class Person implements Comparable<Person>{
     7     private String name;
     8     private Integer age;
     9     public Person(String name,Integer age) {
    10         this.name=name;
    11         this.age=age;
    12     }
    13     @Override
    14     public String toString() {
    15         return "Person [name=" + name + ", age=" + age + "]"+"
    ";
    16     }
    17     @Override
    18     public int compareTo(Person o) {
    19         if(this.age>o.age) {
    20             return 1;
    21         }else if(this.age<o.age) {
    22             return -1;
    23         }else {
    24             return this.name.compareTo(o.name);
    25         }
    26     }
    27     @Override
    28     public int hashCode() {
    29         final int prime = 31;
    30         int result = 1;
    31         result = prime * result + ((age == null) ? 0 : age.hashCode());
    32         result = prime * result + ((name == null) ? 0 : name.hashCode());
    33         return result;
    34     }
    35     @Override
    36     public boolean equals(Object obj) {
    37         if (this == obj)
    38             return true;
    39         if (obj == null)
    40             return false;
    41         if (getClass() != obj.getClass())
    42             return false;
    43         Person other = (Person) obj;
    44         if (age == null) {
    45             if (other.age != null)
    46                 return false;
    47         } else if (!age.equals(other.age))
    48             return false;
    49         if (name == null) {
    50             if (other.name != null)
    51                 return false;
    52         } else if (!name.equals(other.name))
    53             return false;
    54         return true;
    55     }
    56 }
    57 
    58 public class TestDemo{
    59     public static void main(String[] args) throws Exception {
    60         Set<Person> set=new HashSet<Person>();
    61         set.add(new Person("张三",20));
    62         set.add(new Person("张三",20));//重复数据
    63         set.add(new Person("李四",20));//年龄重复
    64         set.add(new Person("王五",19));
    65         System.out.println(set);
    66     }
    67 } 

      如果要想标识出对象的唯一性,一定需要hashCode() equals()两个方法共同作用

    面试题:如果两个对象的hashCode()相同 equals()不同结果是什么?不能

    面试题:如果两个对象的hashCode()不相同 equals()相同是什么?不能消除

      对象判断必须两个相同才能实现 

      在很多时候用Set集合的核心目的不是让其进行排序,而是让其进行重复元素的过滤,那么使用TreeSet就没有意义的,重复元素有需要依靠hashCode() equals()方法,如果不是必须的时候,在使用Set接口的时候尽量用系统提供的类去实现,

    例如:String Integer

    原则:

      保存自定义类对象一定用List接口

      保存系统类的信息的时候一定使用Set接口

  • 相关阅读:
    Android必学——AsyncTask
    成员变量 局部变量
    Java中private、protected、public和default的区别
    实现图片的一个轮转功能
    vmware14克隆后UUID相同的解决方法
    curl
    python3 configparser模块
    python2.7系统性能监控psutil模块
    mysql5.7.22tar包安装
    通过pip3安装ipython
  • 原文地址:https://www.cnblogs.com/Tony98/p/10557778.html
Copyright © 2011-2022 走看看