集合继承图集合总结

引用的别人的继承图

Collection和接口及其继承接口继承的特点
在这里插入图片描述

List集合存储元素的特点:

1.List集合元素存储特点:
有序可重复。
有序:存进去的顺序和取出的顺序相同,每- -个元素都有下标。。
可重复:存进去1,可以再存储一个1
2. list 既然是Collection接口的子接口,那么肯定list接口有自己“特色”的方法:
以下只列出List接口特有的常用的方法:
void add(int index, E element) 添加元素(下标,元素)
E get(int index) 通过下标获取元素 E代表Object
t indexOf(object o) 获取某对象第一次出现处的索引,如果没有这个元素,输出-1
int lastIndexOf(object o)
获取某对象最后一次出现处的索引,如果没有这个元素,输出-1,如果有,输出下标
List是可重复的。如果有两个元素相同 输出的是最后一个元素的的索引
E remove(int index) 删除指定下标位置的元素
E set(int index, E element) 修改指定下标位置的元素

实现类ArryList

ArrayList集合:
1、默认初始化容量10 (底层先创建了一个长度为的数组,当添加第- - 个元素的时候,初始化容量10。)
2、集合底层是-10bject[]数组。
3、构造方法:
new Arraylist();
new ArrayList(20);
4、ArrayList集合的扩容:?
增长到原容量的1.5倍。
Arraylist集合底层是数组,怎么优化?
尽可能少的扩容。因为数组扩容效率比较低,建议在使用Arraylist集合
的时候预估计元素的个数,给定一个初始化容量。
5、数组优点:
检索效率比较高。( 每个元素占用空间大小相同,内存地址是连续的,知道首元素内存地址,
然后知道下标,通过数学表达式计算出元素的内存地址,所以检索效率最高。)
6、数组缺点:
随机增删元素效事比较低。
另外数组无法存猪大数据量。( 很难找到-块非常巨大的连续的内存空间。|)
7、向数组末尾添加元素,效率很高,不受影响。
8、面试官经常问的一个问题?
这么多的集合中,你用哪个集合最多? .
答:ArrayList集合。
因为往数组末尾添加元素,效率不受影响。
另外,我们检索/查找某个元素的操作比较多。

以下是ArrayList常用的方法和两种遍历方式

public static void main(String[] args) {
    List list = new ArrayList();

    //添加元素 默认向集合末尾添加 有下标 List接口
    list.add("1");
    list.add("2");
    list.add("3");
    list.add("4");
    list.add("King");


    //列表指定位置添加元素
    //用的不多对于ArryList集合效率较低
    list.add(2,"King");

    //根据下表获取元素
    Object object = list.get(0);
    System.out.println(object);


    //List集合有下标 特有的方法遍历
    for (int i = 0 ; i < list.size() ; i++){
        Object object2 = list.get(i);
        System.out.println(object2);
    }
    System.out.println("索引");
    //获取某对象第一次出现处的索引,如果没用这个元素,输出-1
    System.out.println(list.indexOf("1"));

    //获取某对象最后一次出现处的索引,如果没用这个元素,输出-1
    //List是可重复的。如果有两个元素相同 输出的是最后一个元素的的索引
    System.out.println(list.lastIndexOf("King"));

    //删除指定下标的元素
    list.remove(0);
    System.out.println(list.size());

    System.out.println("------------------------------");

    //修改指定下标的元素
    list.set(4, "mymy");
    
    //List集合有下标 特有的方法遍历
    for (int i = 0 ; i < list.size() ; i++){
        Object object3 = list.get(i);
        System.out.println(object3);
    }
    //迭代器方式遍历
    Iterator iterator = list.iterator();

    while (iterator.hasNext()){
        System.out.println(iterator.next());
    }


}

实现类LInkedList

Linkedlist集合有初始化容量吗?没有。
没有,最初这个链表中没有任何元素。first和last引用都是null。
不管是L inkedlist还是ArrayList ,以后写代码时不需要关心具体是哪个集合。
因为我们要面向接口编程,调用的方法都是接口中的方法。

list list2 = new Arraylist(); //这样写表示底层你用了数组。
List list2 = new LinkedList(); //这样写表示底层你用了双向链表。
链表的优点:
由于链表上的元素在空间存储上内存地址不连续。
所以随机增删元素的时候不会有大量元素位移,因此随机增删效率较高。
在以后的开发中,如果遇到随机增删集合中元素的业务比较多时,建议
使用inkedList。
链表的缺点:
不能通过数学表达式计算被查找元素的内存地址,每- -次查找都是从头
节点开始遍历,直到找到为止。所以inkedlist集合检索/查找的效率
较低。
Arraylist :把检索发挥到极致。( 末尾添加元素效宰还是很高的)
Linkedlist :把随机增删发挥到极致。
加元素都是往末尾添加,所以ArrayL ist用的比inkedlist多。

单向链表
单向链表特点
双向链表结构图
在这里插入图片描述

Vector实现类

1、底层也是一个数组。
2、初始化容量: 10
3、怎么扩容的?
扩容之后是原容量的2倍。
10–> 20 --> 40 --> 80
4. Arraylist集合扩容特点:
ArrayList集合扩容是原容量1.5倍。
5、Vector中所有的方法都是线程同步的,都带有synchronized关键字,
是线程安全的。效率比较低,使用较少了。
6、怎么将-一个线程不安全的ArrayList集合转换成线程安全的呢?不建议这样使用,因为含有并发的问题
使用集合工具类:
java. util. Collections;
java.util.Collection是集合接口。
java. util.Collections是集合工具类。

Set集合存储元素的特点:

无序 不可重复。
无序:存进去的顺序和取出的顺序不一定相同。 另外Set集合中元素没有下标。
不可重复:存进去1,不能再存储1了。

HashSet实现类

注意:Map集合的key,就是一个Set集合。往Set集合中放数据,实际上放到了Map集合的key部分。
实际上HashSet集合在new的时候,底层实际上new了一个HashMap集合.向HashSet集合中存储元索,实际上是存储到HashMap集合中了.
boolean add(0bject e)向集合中添加元素
int size()获取集合中元素的个数
void clear()清空集合
boolean contains(object o)判断当前集合中是否包含元素o,包含返回true ,不包含返回false
boolean remove​(Object o)删除集合中的某个元素
boolean isEmpty( )判断该集合中元素的个数是否为0

sorteSet接口继承了Set接口

Sor tedSet集合存储元素的特点:
由于继承了Set完合,所以它的特点
也是无序不可重复,但是放在SortedSet,集合中的元索可以自动排序。
我们成为可排序集合。放到该集合中的元素是自动按照大小顺序排序的。

TreeSet实现类

TreeSet实现类继承了sorteSet接口,所以是可排序的
TreeSet集合底层实际.上是TreeMap
new TreeSet集合的时候,底层实际上
new了一个TreeMap集合.
往TreeSet集合中放数据的时候,实际上
是将数据放到TreeMap集合中了.
TreeMap集合底层采用了二叉树数据结构
重点:实现可排序的
例如TreeSet tr = new TreeSet<>(); 其中String类里已经继承了Comparable这个接口并且实现了compareTo这个方法所以不需要重写。

放到TreeSet或者TreeMap集合key部分的元素要想做到排序,包括两种方式:
第一种:放在集合中的元素实现java. lang. Comparable接口。
第二种:在构造TreeSet或者TreeMap集合的时候给它传一个比较器对象。
Comparable和Comparator态么选择呢?
当比较规则不会发生改变的时候,或者说当比较规则只有1个的时候,建议实现Comparable接口。
如果比较规则有多个,并且需要多个比较规则之间频繁切换,建议使用Comparator接口。
Comparator接口的设计符合OCP原则。

第一种:Comparable
以下举例了两个 需要注意在自定义类里需要实现compareTo方法方法,并且重写toString

//自定义类排序
public class TreeSetTest01 {
    public static void main(String[] args) {
        Customer c1 = new Customer(100);
        Customer c2 = new Customer(6);
        Customer c3 = new Customer(20);
        Customer c4 = new Customer(10);

        //创建TreeSet集合
        TreeSet<Customer> treeSet = new TreeSet<>();

        //添加元素

        treeSet.add(c1);
        treeSet.add(c2);
        treeSet.add(c3);
        treeSet.add(c4);

        //遍历
        for (Customer c : treeSet){
            System.out.println(c);
        }
    }
}
//自定义类,实现Comparable里的compareTo方法,注意需要给Comparable规定类型
class Customer implements Comparable<Customer>{
    int age;

    public Customer(int age) {
        this.age = age;
    }

    //重写coparerTO方法 比较规则由自己定 升序或者降序
    @Override
    public int compareTo(Customer customer) {
        return this.age - customer.age;
    }

    @Override
    public String toString() {
        return "Customer{" +
                "age=" + age +
                '}';
    }
}
public class TreeSetTest02 {
    public static void main(String[] args) {
        TreeSet<Vip> treeSet = new TreeSet<>();
        treeSet.add(new Vip(19, "zhangsan"));
        treeSet.add(new Vip(20, "zhangsan"));
        treeSet.add(new Vip(19, "zhangsi"));
        treeSet.add(new Vip(21, "xiaoliu"));

        for (Vip vip : treeSet){
            System.out.println(vip);
        }
    }
}
自定义类,实现Comparable里的compareTo方法,注意需要给Comparable规定类型
class Vip implements Comparable<Vip>{
    int age;
    String name;

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

    @Override
    public int compareTo(Vip vip) {
        //年龄相同时,按照名字排序
        //名字是String 可以直接比
        if (vip.age == this.age)
            return this.name.compareTo(vip.name);
        else   return this.age - vip.age;
    }

    @Override
    public String toString() {
        return "Vip{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}

第二种Comparator

//TreeSet中元素可排序的第二种方式: 使用比较器
public class TreeSetTset06 {
    public static void main(String[] args) {
        //创建TreeSet集合对象的时候,需要使用比较器
        //给构造方法一个比较器
        TreeSet<WuGUi> wuGUis = new TreeSet<>(new WUGUiComparator());

        //或者new一个匿名内部类 并且实现
   /*     TreeSet<WuGUi> wuGUiss = new TreeSet<>(new Comparator<WuGUi>() {
            @Override
            public int compare(WuGUi wuGUi, WuGUi t1) {
                return 0;//这里没重写方法需要重写
            }
        });*/
        wuGUis.add(new WuGUi(1000));
        wuGUis.add(new WuGUi(800));
        wuGUis.add(new WuGUi(1010));

        for (WuGUi w : wuGUis){
            System.out.println(w);
        }

    }
}
class WuGUi{
    int age;

    public WuGUi(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "WuGUi{" +
                "age=" + age +
                '}';
    }
}
//编辑一个类,实现比较器的方法
class WUGUiComparator implements Comparator<WuGUi>{
    @Override
    public int compare(WuGUi wuGUi, WuGUi t1) {
        return wuGUi.age - t1.age;
    }
}

二叉树原理
二叉树

Map集合

在这里插入图片描述
1、Map集合和Clletion集合没有关系。
2、Map集合以key和value的这种键值对的方式存储元素. .
3、key 和value都是存储java对象的内存地址。
4、所有Map集合的key特点:无序不可重复的。
Map集合的key和Set集合存储元素特点相同。
java. util .Map接口中常用的方法:
1. Map和collection没有继承关系。
2. Map集合以key称value的方式存储数据:键值对
key称value都是引用数据类型。
key.称value都是存储对象的内存地址。
key.起到主导的地位, value是key的一个附属品。
3. Map接口中常用方法:
V put(K key, V value) 向Map集合中添加键值对
V get(Object key) 通过key获取value
void clear()清空Map集合
boolean containsKey(object key)判断Map 中是否包含某个key
boolean containsValue(object value) 判断Map 中是否包含某个value
boolean isEmpty( )判断Map集合中元素个数是否为0
Set keySet() 获取Map集合所有的key (所有的键是- -个set集合)
V remove(object key)通过key删除键值对
int size() 获取Map集合中键值对的个数。
Collection values() 获取Map集合中所有的value,返回一个Collection
Set<Map. Entry<K, V>> entrySet()将Map集合转换成set集合

假设现在有一个Map集合,如下所示:
map1集合对象
key value
1 zhangsan
2 lisi
3 wangwu
4 zhaoliu
Set set = map1. entrySet();
set集合对象
注意: Map集合通过entrySet()方法转换成的这个Set集合, Set集合中元素的类型是Map. EntryMap. Entry和String一样,都是一种类型的名字,只不过: Map.Entry是静态内部类
1=zhangsan
2=lisi
3=wangwu
4=zhaoliu

HashMap实现类的基本概念

HashMap集合底层是哈希表数据结构,是非线程安全的。在JDK8之后,如果哈希表单向链表中元素超过8个,单向链表这种数结构会变成红黑树数据结构。.当红黑树上的节点数里小于6时,会重新把红黑树变成单向链表数据结构。这种方式也是为了提高检索效率,二叉树的检索会再次缩小扫描范围。提高效率。初始化容量16.默认加载因子0.75 扩容是:扩容之后的容量是原容里的2倍。
HashMap集合的key和value允许null
HashMap集合:
1. HashMap集合底层是哈希表/散列表的数据结构。
2、哈希表是一个怎样的数据结构呢?
哈希表是一个数组和单向链表的结合体。
数组:在查询方面效率很高,随机增删方面效率很低。
单向链表:在随机增删方面效宰较高,在查询方面效率很低。
哈希表将以上的两种数据结构融合在一起,充分发挥它们各自的优点。
3. HashMap集合底层的源代码:
public class HashMap{
// HashMap底层实际上就是一个数组。(-一维数组 )
Node<K,V>[] table;
//静态的内部类HashMap. Node
static class Node<K,V> {
final int hash; //哈希值(/哈希值(哈希值是key的hashCode()方法的执行结果。hash值通过哈希函数/算法,可以转换存储成数组的下标)
final K key; //存储到Map集合中的那个key
V value; //存储到Map集合中的那个value
Node<K,V> next; //下一个节点的内存地址。
}
}
哈希表/散列表: 一维数组,这个数组中每一个元素是一个单向链表。( 数组和链表的结合体。)
*/
4、最主要掌握的是:
map.put(k,v)
V = map.get(k)
以上这两个方法的实现原理,是必须掌握的。
5. HashMap集合的key部分特点:
无序,不可重复。
**为什么无序?**因为不一定挂到哪个单向链表上。
不可重复是怎么保证的? equals方法来保证HashMap集合的key不可重复。
如果key重复了, value会覆盖。
放在HashMap.集合key部分的元素其实就是放到HashSet集合中了。
所以HashSet集合中的元素也需要同时重hashCode()+equals()方法。
6、哈希表HashMap 使用不当时无法发挥性能!
假设将所有的hashCode().方法返回值固定为某个值,那么会导致底层哈希表变成了
纯单向链表。这种情况我们成为:散列分布不均匀。
什么是散列分布均勻?
假设有100个元素, 10个单向链表,那么每个单向链表上有10个节点,这是最好的,
是散列分布均匀的。
假设将所有的hashCode()方法返回值都设定为不一样的值,可以吗,有什么问题?
不行,因为这样的话导致底层哈希表就成为一维数组了,没有链表的概念了。
也是散列分布不均匀。
散列分布均匀需要你重写hashCode()方法时有一定的技巧。
7、重点:放在HashMap集合key部分的元素,以及放在HashSet集合中的元素,需要同时重导hashCode和equals方法。
8、HashMap集合的默认初始化容量是16 ,默认加载因子是0.75
这个默认加载因子是当HashMap集合底层数组的容量达到75%的时候,数組开始扩容。
重点,记住:HashMap集合初始化容量必须是2的深幂,这也是宫方推荐的,
这是因为达到散列均匀,为了提高HashMap集合的存取效率,所必须的。
9.对于哈希表数据结构来说:
如果o1和o2的hash值相同,-定是放到同一个单向链表上。
当然如果o1和o2的hash值不同,但由于哈希算法执行结束之后转换的数组下标可能相同,此时会发生“哈希碰撞”。|
HashMap集合key部分允许null吗?
允许
但是要注意: HashMap集合的key null 值只能有一个。因为key值重复value要被覆盖
有可能面试的时候遇到这样的问题。

equals方法的调用
**
11向Map集合中存,以及Map集合中取,都是先调用key的hashCode方法,然后再调用equals方法!
equals方法有可能调用,也有可能不调用。
put(k,v)举例,什么时候equals不会调用?k. hashCode()方法返回哈希值,哈希值经过哈希算法转换成数组下标。数组下标位置上如果是null , equals不需要执行。
拿getk)举例,什么时候equals不会调用?k. hashCode()方法返回哈希值,哈希值经过哈希算法转换成数组下标。数组下标位置上如果是null , equals不需要执行。
12、注意:如果一个类的equals方法重写了,那么hashCode()方注必须重写。
并equals方法返回如果是true , hashCode()方法返回的值必须- -样。
equals方法返回true表示两个对象相同,在同一个单向链表上比较。
那么对于同一个单向链表.上的节点来说,他们的哈希值都是相同的。
所以hashCode()方法的返回值也应该相同。
13. hashCode()方法和equals()方法不用研究了,直接使用IDEA工具生成,但是这两个方法需要同时生成。
终极结论:.
放在HashMap集合key部分的,以及放在HashSet集合中的元素,需要同时重导hashCode方法和equals方法。

HashMap常用的方法
V put​(K key, V value) 添加键值对
V get​(Object key) 通过key 获取value 返回值是value 如果没有找到,返回null
boolean isEmpty() 判断哈希表是否为空
int size() 查看集合中元素的个数
V remove​(Object key) 通过key 删除key—value
boolean containsKey​(Object key) 查看是否包含某个key
boolean containsValue​(Object value) 查看是否包含某个value注意//contains方法都是调用的eqlus方法比对,如果自定义类需要重写

public class MapTest {
    public static void main(String[] args) {
        //创建Map对象
        Map<Integer,String> map = new HashMap<>();
        //向Map集合中添加键值对
        map.put(1, "zhangsan");
        map.put(2, "lisi");
        map.put(3, "wangwu");
        map.put(4, "xiaoliu");

        //通过key获取value
        String value = map.get(2);
        System.out.println(value);

        //获取键值对数量
        System.out.println("键值对数量 : " + map.size());

        //通过key删除 key-value
        map.remove(2);
        System.out.println(map.get(2));

        //获取键值对数量
        System.out.println("键值对数量 : " + map.size());

        //判断是否包含某个k
        System.out.println(map.containsKey(1));
        //contains方法都是调用的eqlus方法比对,如果自定义类需要重写
        //判断是否包含某个value
        System.out.println(map.containsValue("xiaoliu"));

        //获取Map集合中所有的key(所有的键是一个set集合)

        Collection<String> values = map.values();
        for (String s : values){
            System.out.println(s);
        }

        //清空键值对
        map.clear();
        System.out.println("键值对数量 : " + map.size());

        //判断是否为空
        System.out.println(map.isEmpty());

    }
}

两种遍历方式:

public class MapTset02 {
    public static void main(String[] args) {
        //Map集合的遍历
        Map<Integer,String> map = new HashMap<>();
        map.put(1, "zhangsan");
        map.put(2, "lisi");
        map.put(3, "wangwu");
        map.put(4, "xiaoliu");
        //遍历Map集合
        //第一种方式: 获取所有的key,通过key 遍历value
        //先获取所有的key
        Set<Integer> keys = map.keySet();
        //遍历key,通过key 获取value
        //迭代器
      /*  Iterator<Integer> it = keys.iterator();
        while (it.hasNext()){
            Integer key = it.next();
            String value = map.get(key);
            System.out.println(key + " = " + value);
        }*/
        //foreach

        for (Integer key : keys){
            System.out.println(key + "=" + map.get(key));
        }

        System.out.println("-----------------------------------");

        //第二种方式 Set<Map.Entry<K,V>> entrySet()
        //这种方式适合大数据量,直接从node里获取。效率高
        //以上这种方式把Map集合转换成Set集合
        //Set集合中元素类型:Map.Entry
        Set<Map.Entry<Integer,String>> set = map.entrySet();
        //遍历Set集合,每一次取出一个Node
        Iterator<Map.Entry<Integer,String>> it2 = set.iterator();
        while (it2.hasNext()){
            Map.Entry<Integer,String> node = it2.next();//这里用迭代器获取了key和value相对应的类型返回到node里
            Integer key = node.getKey(); //获取node里的key
            String value = node.getValue(); //获取node里value
            System.out.println(key + "=" + value);
        }

        for (Map.Entry<Integer,String> entry : set){
            System.out.println(entry.getKey() + " = " + entry.getValue());
        }
    }
}

哈希表存放数据的原理
在JDK8之后,如果哈希表单向链表中元素超过8个,单向链表这种数结构会变成红黑树数据结构。当红黑树上的节点数里小于6时,会重新把红黑树变成单向链表数据结构。这种方式也是为了提高检索效率,二叉树的检索会再次缩小扫描范围。提高效率。初始化容量16.默认加载因子0.75 扩容是:扩容之后的容量是原容里的2倍。在这里插入图片描述

Hashtable实现类

Hashtable的key可以为null吗?
Hashtable的key和value都是不能为null的。
HashMap集合的key称value都是可以为null的。
Hashtable方法都带有synchronized :线程安全的。线程安全有其它的方案,这个Hashtable对线程的处理,导致效率较低,使用较少了。
Hashtable.和HashMap一样,底层都是哈希表数据结构。
Hashtable的初始化容量是11 ,默认加载因子是:0.75f
Hashtable的扩容是:原容量*2+1

Properties类继承Hashtable

Properties是线程安全的,因为继承Hashtable,另外Properties存储元素的时侯也是采用key和value的形式存储,并且key和value 只支持String类型,不支持其它类型。Properties被称为属性类。
掌握 存和取 元素
Object setProperty​(String key, String value); 调用Hashtable方法put方法,存key–value
String getProperty​(String key); 通过key 返回value的值

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值