Java集合框架Collections【List/Set】

  1. 集合就是存放对象的,他比数组好的一点就是他一开始不清楚自己长度
    容器一般是分为很多种的,很多的容器在一起然后进过断的抽象和抽取就成了一个体系,我们称之为集合框架
    我们看体系首先是看顶层的容器,他是底层的容器都有的特性,然后在逐步求精
    最顶层的我们称之为collection 在util包中的

  2. 在collection中分为两个比较常用的子接口分别是list和set。
    list是类似于数组的那种,也就是集合元素可重复,有序有脚标。
    set则为无序的,所以集合元素不可重复,不可脚标查找
    以下是List的通用方法:

    • 添加元素:
      add(index,data)
    • 删除元素:
      remove(index)
    • 修改元素:
      set(index,data)
    • 获取元素:
      get(index) 配合for循环
    • 迭代器
      indexOf(data)
      subList(start,end)

    在list中有一个特殊的迭代器,其他的集合都没有只是list有叫做ListIterater
    这个迭代器比一般的迭代器会多非常多的功能

    另外注意的一点就是在使用iterater进行list迭代的时候,不能够使用集合的方法对集合进行增删改查的操作
    否则就会出现一个运行时异常,主要原因就是同时操作一个集合导致不合法,类似于同时IO同一块数据块
    因此在迭代的过程中只能使用迭代器提供的操作集合的方法
    或者不使用迭代器,直接使用原生的for循环,然后直接就可以使用迭代器的方法进行对集合的操作

  3. add方法接受的参数类型为object以便于接受任意类型的参数
    集合中存放的是对象的地址而不是对象本身
    对象可以直接被打印

  4. List可以分为三种,但是常用的只有两种,他们之间的主要区别就是底层的数据及结构不一样。

  • ArrayList 底层的实现使用的是数组,也就是说类似于数组构成的线性表,查询快增删慢,而且他是不同步的
  • LinkedList 底层使用的是链表,那么就会出现查询慢,增删快
  • Vector 底层和ArrayList完全一样,只不过vector就是jdk1.0出现的那时候还没有集合框架,后来有了集合框架被分到List里面,目前被ArrayList代替因为他是同步的速度慢,我们都是用Arraylist然后自己写锁来手动同步
  1. arraylist和vector之间区别还有就是他们们的迭代方式可以有不同,由于vector是最先出来的,所以说他一开始用的并不是
    iterator迭代器而是枚举enumeration他和迭代器很相似,目前由于枚举不好记就用iterator。另外arraylist和vector使用的
    是变长数组,也就是本来都是固定长度10个元素,然后如果查过十个以后ArrayList使用的是50%的增长也就是会变成15个,二vector则是
    直接100%增长20个
    枚举的代码如下:

        public class Enmu {
            public static void main(String[] args) {
                Vector v=new Vector();
                v.add("1");
                v.add("2");
                v.add("3");
                Enumeration e=v.elements(); //定义枚举
                while (e.hasMoreElements()){  //循环遍历
                    System.out.println(e.nextElement());
                }
            }
        }
    
  2. LinkedList中除了一般的List的通用方法还有他自己特有的方法,而且比较重要

    • addFirst
    • addLast
    • getFirst 获取元素但是不删除元素
    • getLast
    • removeFirst 获取元素而且删除元素,但是如果给的是一个空的链表列表使用此方法会产生异常因此有了以下替代方法
    • removeLast
    • offerFirst 添加
    • offerLast
    • peekFirst 获取
    • peekLast
    • pollFirst 删除
    • pollLast 空链表列表也不会有异常而是直接返回null

    代码如下:

        public class LinkedList_5 {
            public static void main(String[] args) {
                LinkedList list=new LinkedList();
                list.addFirst("1");
                list.addFirst("2");
                list.addFirst("3");
                System.out.println(list.getFirst());
                System.out.println(list.removeFirst());
    
                LinkedList list1=new LinkedList();
                list1.offerFirst("1");
                list1.offerFirst("2");
                list1.offerFirst("3");
                System.out.println(list1.peekFirst());
                System.out.println(list1.pollFirst());
    
            }
        }
    

7.使用LinkedList实现堆栈和队列结构也就是他所特有的addFirst addLast 以及remove方法的使用
只是要注意在LinkedList里面添加和删除的元素都是object而不是一般的对象,应该说
所有的集合框架里面的东西都是接受object对象的 所以在写具体的函数的时候注意一下

8.使用ArrayList写几个小程序,第一个就是使用ArrayList去处重复元素,其中的元素就是字符串,而第二个则是
去除的某些自定义对象。第二个程序也揭示了对于List集合中的元素的比较的接口就是contains他底层是调用
的对象的equals方法,对于remove也是底层调用了equals方法从而进行比较和删除。所以说重点在于重写
equals方法。
另外在迭代器中每使用一次next方法必须要进行一次hasNext的判断否则很有可能出现找不到元素的情况
例如一个hasNext里面有两个next方法,而元素又为奇数个时候会抛异常

        class Person{
            private String name;
            private int age;
            Person(String name,int age){
                this.name=name;
                this.age=age;
            }
            String getName(){
                return this.name;
            }
            private int getAge(){
                return this.age;
            }
            public boolean equals(Object object){
                if (!(object instanceof Person)){
                    return false;
                }
                Person person=(Person)object;  //注意这个地方必须要强转否则会出现下面的person无法调用方法
                return this.name.equals(person.getName()) && this.age==person.getAge();
            }
        }
        public class ArrayList_7 {
            private static ArrayList<Person> singleElement(List<Person> al){
                ArrayList<Person> newAl=new ArrayList<Person>();
                Iterator<Person> it=al.iterator();
                while (it.hasNext()){
                    Person tmp= it.next();  //iterator返回的是object所以必须要强转
                    if (!newAl.contains(tmp)){
                        newAl.add(tmp);
                    }
                }
                return newAl;
            }

            public static void main(String[] args) {
                ArrayList<Person> al=new ArrayList<>();
                al.add(new Person("zhang01",1));
                al.add(new Person("zhang02",2));
                al.add(new Person("zhang03",1));
                al.add(new Person("zhang03",1));
                al=singleElement(al);
                for (Person per : al) {   //可以使用这种更好的语言结构来实现迭代省去了iterator迭代 也不用考虑向下类型转换
                    System.out.println(per.getName());
                }
            }
        }

9.Set中存放的元素都是无序的并且里面的元素都是不可重复的,显然如果只存放字符串的话很容易就知道是否重复
也就无序我们自己去判断是否重复了。
set中的公共方法就是集合框架中共有的方法,重要的还是他的子类,这里有两个就是hashSet和TreeSet

而存放一般的自定义对象的时候我们发现如果想要某些属性一致的对象作为重复对象
的话hashSet自身是做不到的,所以我们需要了解hashSet的底层层放原理,hashSet底层就是hash表,在存放元素的时候
首先来判断存放的元素的hashCode值是否一样也就是调用他们的hashCode方法,注意hashCode是object对象的方法,所以
所有的对象都有此方法,另外如果他们的hashCode是一样的然后就调用他们的equals方法.不一样则就存进去一样则被踢出去
那么说白了hashSet底层判断是否为重复元素做了两件事第一个就是判断他们的hashCode第二个就是equals方法
如果要自定义对象如何存放就要重写这两个方法,但是重写的时候一定要注意他们的参数列表否则肯定不会生效,hashCode
一般来说也尽量不要让不同的对象的hashCode一致造成多余的比较

对于元素判断是否存在和删除元素都是hashCode和equals方法

下面是hashSet的代码示例:

  class People{
      private String name;
      private int age;

      People(String name,int age){
          this.name=name;
          this.age=age;
      }

      String getName(){
          return this.name;
      }

      private int getAge(){
          return this.age;
      }

      public int hashCode(){
          return name.hashCode()+age;
      }

      public boolean equals(Object object){
          if (!(object instanceof People)){
              return false;
          }
          People person=(People)object;  //注意这个地方必须要强转否则会出现下面的person无法调用方法
          return this.name.equals(person.getName()) && this.age==person.getAge();
      }

  }

  public class HashSet_8 {
      public static void main(String[] args) {
          HashSet<People> hs=new HashSet<People>();
          hs.add(new People("1",11));
          hs.add(new People("2",11));
          hs.add(new People("1",11));
          for (People pe:hs){
              System.out.println(pe.getName());
          }
      }
  }

10.treeSet是在集合中的元素会自动排序,如果是字符串什么的他们都可以自动比较,因为字符串是已经实现了Compareable接口
但是如果要存放一般的元素对象的时候注意一定要让改类实现compareable接口,因为此接口会让类强制具有比较性
然后复写此接口中的compareTo方法,大于返回正数等于为零小于则为负,这里要注意如果有多个排序元素的话然后在比较
的时候相等条件判断要注意对其他排序元素的判断,否则会造成某个条件相等但是并不是同一个元素而无法存入

class Student implements Comparable{
 private String name;
 private int age;

 Student(String name,int age){
     this.name=name;
     this.age=age;
 }

 public String getName() {
     return name;
 }

 public int getAge() {
     return age;
 }

 @Override
 public int compareTo(Object o) {
     if (!(o instanceof Student)){
         throw new RuntimeException("not same type");
     }
     if (this.age>((Student) o).age){
         return 1;
     }else if (this.age==((Student) o).age){
         return this.name.compareTo(((Student) o).name);
         //注意多重判断,要是age一样的话他们就会被当成相同元素而无法插入  string类已经实现了comparable接口
         //其实java中很多类都实现了comparable接口,让类具有可比性
     }
     return -1;
 }
}

public class TreeSet_9 {
 public static void main(String[] args) {
     TreeSet<Student> ts=new TreeSet<>();
     ts.add(new Student("ab",1));
     ts.add(new Student("kb",3));
     ts.add(new Student("mb",3));
     ts.add(new Student("am",7));
     for (Student stu :
             ts) {
         System.out.println(stu.getName()+"--------"+stu.getAge());
     }
 }
}

11.TreeSet底层的数据结构就是二叉树,元素的排列方式就是第一个进入的元素作为根节点然后按照compareTo方法
返回的值来判定是左孩子还是右孩子,这里就是如果说compareTo方法返回的正数则右孩子,负数为左孩子相等就说明
是同一个元素不用再比较。
所以说决定了TreeSet中的元素的重复与否就是compareTo函数的返回值
那么这样的话我们也可以规定一个TreeSet按照放进去的顺序取出来 或者倒序取出来就是compareTo全部返回1
或者-1即可,当然如果返回的始终为0那么最后集合中只有一个元素就是第一个元素

12.在TreeSet中除了实现comparable接口复写compareTo方法以外还有一种排序方法就是比较器,前面的comparable
接口是让元素具有了比较性而比较器则是让集合具有了比较性这个优先级跟高,具体的方法就是在集合实例化的时候传入一个
自定义的比较器,也就是构造方法传入一个比较器对象,这个比较器也是一个接口要实例化的话需要实现他的compare方法
比较器也是更加常用的


class MyComparator implements Comparator{

 public int compare(Object o1,Object o2){
     Student obj1=(Student)o1;
     Student obj2=(Student)o2;
     int num=obj1.getName().compareTo(obj2.getName());
     if (num==0){
        return new Integer(obj1.getAge()).compareTo(obj2.getAge());
     }
     return num;
 }
}

public class TreeSet_10 {
 public static void main(String[] args) {
     TreeSet<Student> ts=new TreeSet<Student>(new MyComparator());
     ts.add(new Student("dsf",11));
     ts.add(new Student("dmf",12));
     ts.add(new Student("ddf",13));
     ts.add(new Student("jf",14));
     for (Student stu :
             ts) {
         System.out.println(stu.getName()+"----------"+stu.getAge());
     }
 }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容