JAVA――集合理解

匿名 (未验证) 提交于 2019-12-02 21:52:03

集合复习

一.集合就像一种容器,可以动态的把多个对象的引用

放入到容器中,存储多个数据 。

集合数组都是对多个数据进行存储操作的结构,简称java容器

二、集合框架、

collection接口:单列集合,用来存储一个一个对象

map接口:双列集合,用来存储一对一对的数据

三、collection(为什么不用collection? 因为即有序又无序,即可重复,又不可重复,找不到这样的容器,所以才会用List和Set)

collection的方法:(需要重写元素所在类的equals方法)

  1. add() //添加元素,可以为简单类型,和引用类型 ,返回boolean

    Collection coll=new ArrayList();        coll.add("aa");
  2. addAll(Collection c)//添加集合数据
    Collection coll=new ArrayList(); Collection coll1=new ArrayList(); coll1.add("bb"); coll.addAll(coll1);
  3. clear() //清空集合
    Collection coll=new ArrayList(); coll.add("aa"); coll.clear();
  4. isEmpty() // 判断是否为空,没有元素
    Collection coll=new ArrayList(); coll.add("aa"); coll.clear(); coll.isEmpty();
  5. contains(Object obj)// 是否包含一个对象,判断的是其内容,内容一致则结果为true,内容不一致则结果为false,这里对于String类型,其equals方法已经重写了,故而只需要判断内容是否一致即可,但是对于JAVA BEAN类型,需要重写其equals方法,否则会判断为false。 可看代码后的总结

    例如:

    private String name; private int age; public Person() {    }     public Person(String name, int age) {        this.name = name;        this.age = age;    }     public String getName() {        return name;    }     public void setName(String name) {        this.name = name;    }     public int getAge() {        return age;    }     public void setAge(int age) {        this.age = age;    }     @Override    public String toString() {        return "Person{" +                "name='" + name + '\'' +                ", age=" + age +                '}';    } //重写equals方法,如果不写,则结果为false    @Override    public boolean equals(Object o) {        System.out.println("kaishi l ");        if (this == o) return true;        if (o == null || getClass() != o.getClass()) return false;        Person person = (Person) o;        return age == person.age &&                Objects.equals(name, person.name);    } 
    import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Date;  public class Demo {    public static void main(String[] args) {        Collection coll=new ArrayList();        coll.add("aa");        coll.add("bb");        System.out.println(coll.contains("aa"));//true ,判断是否有aa,有,则为true         coll.add(new String ("huhu"));        System.out.println(coll.contains(new String("huhu")));//结果为true,因为string底层已经把equals重写过了,直接判断内容         coll.add(new Person("wwuu",123));        System.out.println(coll.contains(new Person("wwuu",123)));//因为上面已经对Person对象进行重写了equals方法,这里直接判断是否有wuwu,123.有则为true        //如果上面没有对Person对象的equals方法进行重写,那么这里为false        //总结:contains比较的是内容,等于用equals方法进行比较        //我们在判断时,会调用obj对象所在类的equals()方法,故而obj所在类要重写equals()方法。    } } 
  6. containsAll(Collection coll1)//判断coll集合中的所有元素是否都存在于当前集合中(注意是:所有元素,但凡有一个不在,则为false)
    Collection coll=new ArrayList(); Collection coll1=new ArrayList(); coll.add("123"); coll1.add("haha"); coll.addAll(coll1); System.out.println(coll.containsAll(coll1));//true,上面用了addAll()方法,把coll1中的数据都放到了coll中,所以coll包含了coll1,为true coll1.add("uiui"); System.out.println(coll.containsAll(coll1));//false,这里是因为coll1新加了一条数据,而coll中没有这条数据,故而为false
  7. remove(Object obj) (删除某个元素,重写元素所在类的equal()方法)
    coll.remove(new Person("wwuu",123)); System.out.println(coll);//由于上述的方法中已经对Person这个类进行了equals()方法的重写,故而这里是可以对new Person("wwuu",123)这个元素进行删除的,如果不重写equals方法则删除不了
  8. remoeAll(Collection coll)(删除coll中所有的元素,重写元素所在类的equal()方法)
    coll.removeAll(coll1); System.out.println(coll1); System.out.println(coll);
  9. retainAll(Collection coll)(求交集的意思,仅仅保留当前集合中的元素并且该元素同时也在另一个集合中,即获取当前集合与coll的交集,重写元素所在类的equal()方法)
     Collection coll2=new ArrayList();        coll2.add(123);        coll2.add(new String ("huhu"));        coll2.add(new String("bb"));        coll.retainAll(coll2);        System.out.println(coll);
  10. equals(Object o) (这里是判断两个集合是否相等,那么这里的obj必须是集合才行,也要重写元素所在类的equals()方法。对于有序集合,其位置也不必须相同,若为无序集合,其位置可以不同,只需要元素相等即可。)
    Collection coll3= Arrays.asList(123,"huhu","bb"); System.out.println(coll2.equals(coll3));
  11. hashCode() (计算机hashCode哈希值的方法,返回值是int)
    System.out.println(coll3.hashCode());
  12. toArray() (集合转数组)
    Object[] objects = coll3.toArray();         for (Object o: objects) {             System.out.println(o);         }
    拓展一下:数组转集合(使用的时候注意 Arrays.asList(T)的参数是可变形参,根据不同需要看是写int 还是其包装类integer ,int会判断成为一个参数,integer为两个参数)
    List list2 = Arrays.asList(new int[]{123, 455}); List list3 = Arrays.asList(new Integer[]{123, 455}); System.out.println(list2.size());//结果是1,判断一个参数 System.out.println(list3.size());//结果是2,判断2个参数
  13. iterator()(迭代器接口:遍历集合的时候使用)
    Iterator iterator=coll2.iterator(); while (iterator.hasNext()){        System.out.println(iterator.next()); }
    拓展:内部定义了一个remove方法,可以删除集合中的元素
  14. foreach
    foreach(Object obj: coll2){     System.out.println(obj); }

LIst----有序可重复(俗称:动态数组)

他是一个接口,通常用List代替数组,有三个实现类ArrayList、LinkedList、Vector

三者的异同:ArrayList、LinkedList、Vector?

相同点:三个类都实现了List接口;存储数据特点相同,有序,可重复

不同点:

ArrayList源码分析(java.util包下):

JDK7:

ArrayList arraylist=new ArrayList();

JDK8:并没有给原始数组初始化,节省内存空间,这样的方式更好,在我们调用add方法的时候,我们的数组才会被创建好

总结:

LinkedList源码分析

 import java.util.LinkedList;  public class LinkedListTest<E> {     int size;     transient MyNode first;     transient MyNode last;      private static class MyNode<E>{         private E element;         private MyNode prev;         private MyNode next;         public MyNode(MyNode prev, E ele, MyNode next){             this.element=ele;             this.prev=prev;             this.next=next;         }     } //添加元素的方法,里面有一个拼接的方法一个Node分为三部分:【prev】【元素】【next】     public void add(E ele){         appendLast(ele);     }     //定义l节点为last,     public void appendLast(E ele){         MyNode<E> l=last;         MyNode newNode=new MyNode(l,ele,null);         //last节点为新节点         last=newNode;         //判断新节点的【prev】是否为null,是则表示为该新节点为【null】【ele】【null】         //表示新结点为first         //否则,表示不是首节点,则把last的【next】指向新结点         if(l==null){             first=newNode;         }else {             l.next=newNode;         }         size++;     }      public void remove(E obj){         //删除元素         //从头开始遍历,一直遍历到结尾,只要没到结尾就继续遍历         for (MyNode pos=first;pos!=null;pos=pos.next){             //判断,当前元素pos是不是想要删除的元素,是的就进行unlink方法,只要找到了就break             if (pos.element.equals(obj)){                 unlink(pos);                 break;             }         }     }     //这里就是删除元素的方法     private void unlink(MyNode<E> pos){         //首先定义当前pos元素【prev】【ele】【next】         E ele=pos.element;         MyNode<E> prev=pos.prev;         MyNode<E> next=pos.next;         //判断当前元素的【prev】是不是空,如果是空,那就表示是first,为第一个节点         //那就直接把第一个删除,然后把pos后面的节点MyNode<E> next=pos.next 赋值给first         //并把当前元素pos的【next】变成null,就不会指向后面的结点了,就断开连接了         if (prev==null){             first=next;             pos.next=null;         }else {             prev.next=next;             pos.prev=null;         }         //判断当前元素是不是最后一个,如果是就删除最后一个元素,即让前一个元素的变成为最后一个last结点         //否则把下一个元素的【prev】指向prev结点         if (next==null){             last=prev;             pos.prev=null;         }else {             next.prev=prev;             pos.next=null;         }         pos.element=null;         size--;     } } 

Set集合

是接口,存储无序不重复的数据,Set接口继承了Collection接口,同时没有添加新的方法,所以在使用上与List接口的实现类使用方式一致。都是有增加元素的add方法和获取元素个数的size方法

要求:
向set中添加数据,其所在类一定要重写hashCode()和equals()方法;
重写的hashCode()和equals()尽可能地保持一致:即相同对象必须拥有相同散列码(相同对象要有一样的哈希值)

具有三个实现类:

HashSet:作为set接口的主要实现类,线程不安全:可以存储null值

LinkedHashSet:是Hashset的子类,在Hashset基础之上,添加了指针,遍历其内部子类的时候,可以按照添加的顺序遍历。

TreeSet:使用红黑树存储,要求放在TreeSet中的数据必须是同类型,可以按照添加对象的知道属性进行排序

无序不可重复的理解:

1.无序性:解释HashSet集合如何存放元素:

2.不可重复性:HashSet集合是如何保证元素不重复

当给hashset中存放元素的时候会先调用对象的hashCode方法,计算哈希值,根据哈希值来决定当前对象在集合中的存储位置。

计算哈希值得时候减少冲突

链表与数组的区别:

  1. 对于在内存中数据的存放顺序及位置:

    数组中元素是按顺序存放的,那么在内存中也是按顺序存放的,但是链表中元素存放的位置与内存中存放的顺序及位置不一致;

    2.对于扩容的速度:

Map接口

存储双列数据:存储key--value键值对的数据

一、实现类

HashMap:主要实现类;线程不安全,效率高,可以存储null的key和value,key为null可以使用方法,不会报空指针异常
LinkedHashMap---HashMap的子类;保证在遍历map元素时,可以按照添加的顺序实现遍历。

TreeMap:可以按照添加的key-value进行排序,实现遍历,按照key进行排序

Hashtable----是古老实现类;线程安全,效率低,不能存储null的key和value,key为null可以使用方法,会报空指针异常
properties---Hashtable的子类,常用来处理配置文件,key和value嗾使String类型
线程安全

面试题:

1.(高频)HashMap底层实现原理

2.HashMap和Hashtable的异同

二、MAP结构的理解:

三、HashMap的底层原理

哈希冲突:

解决方法1:再哈希法===再次计算哈希值,直到每一个元素都有唯一的索引(位置)为止

解决方法2:链地址法===使用链表

JDK7

import java.util.HashMap;  public class HashMapTest <K,V>{      private Entry<K,V>[]table;     private static final Integer INITCAPACITY=8;     private int size;     public HashMapTest(){         table=new Entry[INITCAPACITY];     }     private int size(){         return size;     }     private V get(Object key){         int hash=key.hashCode();         int i=hash%table.length;         for (Entry<K,V> entry=table[i];entry!=null;entry=entry.next){             if (entry.k.equals(key)){                 return entry.v;             }         }         return null;     }     private V put(K key,V value){          int hash=key.hashCode();         int i=hash%table.length;         for (Entry<K,V> entry=table[i];entry!=null;entry=entry.next){             if (entry.k.equals(key)){                 V oldvalue=entry.v;                 entry.v=value;                 return oldvalue;             }         }         addEntry(key, value, i);         return null;     }      private void addEntry(K key, V value, int i) {         Entry<K,V> entry=new Entry<K,V>(key,value,table[i]);         table[i]=entry;         size++;     }      class Entry<K,V>{         private K k;         private V v;         private Entry<K,V>next;          public Entry() {         }          public Entry(K k, V v, Entry<K, V> next) {             this.k = k;             this.v = v;             this.next = next;         }          public K getK() {             return k;         }          public V getV() {             return v;         }      }      public static void main(String[] args) {         HashMapTest<Integer ,String>hashMapTest=new HashMapTest<Integer, String>();         for(int i=0;i<10;i++){             hashMapTest.put(i,"结束"+i);             System.out.println(hashMapTest.get(i));         }      } }

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!