java进阶5-集合

在这里插入图片描述

数据结构

物理结构

顺序储存结构,在物理储存上是连续的,用索引值指向下一个元素,便于查询,因为有索引号,可以根据索引号直接查询;但不方便增删,因为增删一个,此元素之后的元素的位置都得移动
链式储存结构 可以是连续的也可以是不连续的,一个数据有指针指向下一个元素,便于增删,因为只需增加一个数据,只需将此数据的指针储存于上一个指针,次数据保存下一个数据的指针即可,不需要改变其他的数据;但不便于查询,因为没有索引,就需要遍历,直到找到为止。
线性表,有顺序储存的,也有链式储存的
树,全部元素都用数组的形式储存,根元素、中间元素、叶元素以链表形式,用指针指向彼此之间。
输的根节点的双亲节点为-1;

集合

集合不能直接存储基本数据类型,另外集合也不能直接存储java对象,
集合当中存储的都是java对象的内存地址。(或者说集合中存储的是引用。)

在java中集合分为两大类:
一类是单个方式存储元素:
单个方式存储元素,这一类集合中超级父接口:java.util.Collection;

	一类是以键值对儿的方式存储元素
		以键值对的方式存储元素,这一类集合中超级父接口:java.util.Map;

collection

collection 单列 是一个接口

  • 常用方法
  • add()、remove()、iterator() hashcode()、isempty()、clear()、contains()、size()、toarray()
  • 方法中无改查等方法,只提供了大概的方法
  • Iterator 接口主要方法hasnext()、next()、remove()

collection 包含list和set

list 有序可重复,

  • 常用方法add()、set()、get()indexof()、lastIndexof()
  • list包括ArrayList 、LinkedList 遍历for普通和for增强和Iterator()

Arryaylist

底层是数组 因为有下标,查找方便,增删繁琐;

public class ArrayListTest02 {
    public static void main(String[] args) {

        // 默认初始化容量10
        List myList1 = new ArrayList();

        // 指定初始化容量100
        List myList2 = new ArrayList(100);

        // 创建一个HashSet集合
        Collection c = new HashSet();
        // 添加元素到Set集合
        c.add(100);
        c.add(200);
        c.add(900);
        c.add(50);

        // 通过这个构造方法就可以将HashSet集合转换成List集合。
        List myList3 = new ArrayList(c);
        for(int i = 0; i < myList3.size(); i++){
            System.out.println(myList3.get(i));
        }
    }
}

LinkedList

底层是本质单链表 ,无下标,查找繁琐,只能遍历;增删只需隔断一节链子,改变加入连环前后的索引即可。
他之所以可以用的get()方法,是遍历所得,如get(2),就是全部遍历数据元素后得到数据全部索引,这样就得到索引值为2的值
*用法同ArrayListlist相同

public class LinkedListTest01 {
    public static void main(String[] args) {
        // LinkedList集合底层也是有下标的。
        // 注意:ArrayList之所以检索效率比较高,不是单纯因为下标的原因。是因为底层数组发挥的作用。
        // LinkedList集合照样有下标,但是检索/查找某个元素的时候效率比较低,因为只能从头节点开始一个一个遍历。
        List list = new LinkedList();
        list.add("a");
        list.add("b");
        list.add("c");

        for(int i = 0; i <list.size(); i++){
            Object obj = list.get(i);
            System.out.println(obj);
        }

        // LinkedList集合有初始化容量吗?没有。
        // 最初这个链表中没有任何元素。first和last引用都是null。
        // 不管是LinkedList还是ArrayList,以后写代码时不需要关心具体是哪个集合。
        // 因为我们要面向接口编程,调用的方法都是接口中的方法。
        //List list2 = new ArrayList(); // 这样写表示底层你用了数组。
        List list2 = new LinkedList(); // 这样写表示底层你用了双向链表。

        // 以下这些方法你面向的都是接口编程。
        list2.add("123");
        list2.add("456");
        list2.add("789");

        for(int i = 0; i < list2.size(); i++){
            System.out.println(list2.get(i));
        }

    }
}

set

无序不可重复

  • Set有HashSet和SortedSet

HashSet

本质哈希表;数组的下标是由要储存的值经过哈希算法得来。Hashset就是这样的数组。
哈希表上层是数组,每一个数组下是链路结构。

add原理:

hashset本质是一个数组+链表,上层是数组,数组中是链表,而下标是由要储存的值经过哈希算法得来,经过哈希值得来的下标,是有可能相同的,相同下标的元素,作为一组,每一种中的全部元素,是以链表结构组成的。同一组元素的哈希值,也就是下下标相同,同一个数组中的元素是不相同的,要对比内容,才能区分。
hashset储存一个元素,先把要储存的值,经过哈希算法,得出下标,就要储存在该下标的数组项中,如果该下标中,没用元素,直接储蓄,如果有元素,比较内容后再储存。下标就是hashcode值,比较每个数组项中的链表的值用equals()

用哈希表储存数据元素,需要对数据元素对象重写hashcode()和equals()方法,如下:
hashcode,就是返回数组的下标,equals()就是比较元素是否相同,

public class Student {
    private String name;

    public Student() {
    }

    public Student(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

 

    @Override
    public boolean equals(Object o) {
    //比较地址是否相同
        if (this == o) return true;
        //所要比较的对象是否为空,或者类型是否相同
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        //以上都不是,比较内容是否相同
        return Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(this.name);
    }
}
hashSet常用方法

1、add(Object obj):向Set集合中添加元素,添加成功返回true,否则返回false。

2、size():返回Set集合中的元素个数。

3、remove(Object obj): 删除Set集合中的元素,删除成功返回true,否则返回false。

4、isEmpty():如果Set不包含元素,则返回 true ,否则返回false。

5、clear(): 移除此Set中的所有元素。

6、iterator():返回在此Set中的元素上进行迭代的迭代器。

7、contains(Object o):如果Set包含指定的元素,则返回 true,否则返回false。

public class HashSetTest01 {
    public static void main(String[] args) {
        Set<String> strs = new HashSet<>();

        // 添加元素
        strs.add("hello1");
        strs.add("hello3");
        strs.add("hello4");
        strs.add("hello2");
        // 遍历
        /*
      
        1、存储时顺序和取出的顺序不同。
        2、不可重复。
        3、放到HashSet集合中的元素实际上是放到HashMap集合的key部分了。
         */
        for(String s : strs){
            System.out.println(s);
        }
    }
}

sortedset-----treeset

1、TreeSet集合底层实际上是一个TreeMap
2、TreeMap集合底层是一个二叉树,二叉树可以使顺序结构,也可以是链表结构,但如果二叉树不是满数据结构,而树有很大,顺序机构就太浪费空间,所以二叉树一般是链表结构。链表结构便于增删,而不便于查找,所以我们为链表元素创建编号,也就是可以被指向的的编号,编号又对应着数据元素,所以就能很快找着他。数据在放入树中也是由规则的。
3、放到TreeSet集合中的元素,等同于放到TreeMap集合key部分了。
4、TreeSet集合中的元素:无序不可重复,但是可以按照元素的大小顺序自动排序。
称为:可排序集合。
set集合,包括hashset都是无序的,但为了set存入值时排序,引入treeset,可以排序
treeset底层是一个二叉树,存进去的数据可以按自定义排列,默认升序,sortedset是从大到小

public class TreeSetTest01 {
    public static void main(String[] args) {
        // 创建集合对象
        Set<String> strs = new TreeSet<>();
        // 添加元素
        strs.add("A");
        strs.add("B");
        strs.add("Z");
        strs.add("Y");
        strs.add("Z");
        strs.add("K");
        strs.add("M");
        // 遍历
        /*
            A
            B
            K
            M
            Y
            Z
        从小到大自动排序!
         */
        for(String s : strs){
            System.out.println(s);
        }
    }
}

对自定义对象排序

  • 1.实现compareable接口实现排序
    被添加元素对象实现comparable接口,实现compareTo()方法,元素就有了自定义排序性质,添加元素对象的时候,知道了是实现了comparable接口,就会调用compareTo()方法。
class WuGuiComparator implements Comparator<WuGui> {

    @Override
    public int compare(WuGui o1, WuGui o2) {
        // 指定比较规则
        // 按照年龄排序
        return o1.age - o2.age;
    }
}
  • 2.在构造TreeSet或者TreeMap集合的时候给它传一个比较器对象。
    投入创建用于排序元素对象的类,该类实现comparetor接口,实现compare()方法,compare方法定义被添加元素对象的排序方式。使用时,实例化排序元素对象的实例对象,将实例对象以参数的形式,传入容器的new后的括号中,这样,添加元素时,就会自动排序。
 TreeSet<WuGui> wuGuis = new TreeSet<>(new Comparator<WuGui>() {
            @Override
            public int compare(WuGui o1, WuGui o2) {
                return o1.age - o2.age;
            }
        });

map

put(K key, V value) 向Map集合中添加键值对
get(Object key) 通过key获取value
clear() 清空Map集合
containsKey(Object key) 判断Map中是否包含某个key
containsValue(Object value) 判断Map中是否包含某个value
isEmpty() 判断Map集合中元素个数是否为0
remove(Object key) 通过key删除键值对
size() 获取Map集合中键值对的个数。
Collection values() 获取Map集合中所有的value,返回一个Collection

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

hashmap

HashMap集合的默认初始化容量是16,默认加载因子是0.75
这个默认加载因子是当HashMap集合底层数组的容量达到75%的时候,数组开始扩容。

重点,记住:HashMap集合初始化容量必须是2的倍数,这也是官方推荐的,
这是因为达到散列均匀,为了提高HashMap集合的存取效率,所必须的。

元素是键值对形式的集合,有方法get(“键”),使用keyset()方法可以的到键部分的集合,使用entryset,可以得到键值对的集合,map中键是最终要的。得到的键部分的集合set可以使用set的相关方法,得到的Entyrset部分的集合类型是Set<Map.EntrySet<String,integer>,其中Map.Entryset<String,integer>是一个接口,有方法getKey(),getValue()。
hashmap 键部分底层是hashset,这是最重要的,值部分不重要,map传入的如果是对象,需要向hashset一样重写hashcode()和equals();
hashmap
存放键值对
键取出 set st= map.keyset(); set 是一个存放map集合键部分的集合,就可用set中的方法操作

取出键值对 Set<map.entry<String,Integer>> = map.entryset();

hashmap如果储存的是对象,键储存的对象是hashset,需重写hashcode()函数equal()函数。

public class HashMapTest01 {
    public static void main(String[] args) {
        // 测试HashMap集合key部分的元素特点
        // Integer是key,它的hashCode和equals都重写了。
        Map<Integer,String> map = new HashMap<>();
        map.put(1111, "zhangsan");
        map.put(6666, "lisi");
        map.put(7777, "wangwu");
        map.put(2222, "zhaoliu");
        map.put(2222, "king"); //key重复的时候value会自动覆盖。

        System.out.println(map.size()); // 4

        // 遍历Map集合
        Set<Map.Entry<Integer,String>> set = map.entrySet();
        for(Map.Entry<Integer,String> entry : set){
            // 验证结果:HashMap集合key部分元素:无序不可重复。
            System.out.println(entry.getKey() + "=" + entry.getValue());
        }
    }
}

treemap

主要用于排序,可以自定义key;

Collections

是一个类,里面全是静态方法;

  • 用于操作集合,如sort()
* public class CollectionsTest {
    public static void main(String[] args) {

        // ArrayList集合不是线程安全的。
        List<String> list = new ArrayList<>();
//
//        // 变成线程安全的
        Collections.synchronizedList(list);
//
        // 排序
        list.add("abf");
        list.add("abx");
        list.add("abc");
        list.add("abe");

        Collections.sort(list);
        for(String s : list){
            System.out.println(s);
        }

        List<WuGui2> wuGuis = new ArrayList<>();
        wuGuis.add(new WuGui2(1000));
        wuGuis.add(new WuGui2(8000));
        wuGuis.add(new WuGui2(500));
        // 注意:对List集合中元素排序,需要保证List集合中的元素实现了:Comparable接口。
        Collections.sort(wuGuis);
        for(WuGui2 wg : wuGuis){
            System.out.println(wg);
        }

        // 对Set集合怎么排序呢?
        Set<String> set = new HashSet<>();
        set.add("king");
        set.add("kingsoft");
        set.add("king2");
        set.add("king1");
        // 将Set集合转换成List集合
        List<String> myList = new ArrayList<>(set);
        Collections.sort(myList);
        for(String s : myList) {
            System.out.println(s);
        }

//         这种方式也可以排序。
//        Collections.sort(list集合, 比较器对象);
    }
}

class WuGui2 implements Comparable<WuGui2>{
    int age;
    public WuGui2(int age){
        this.age = age;
    }

    @Override
    public int compareTo(WuGui2 o) {
        return this.age - o.age;
    }

    @Override
    public String toString() {
        return "WuGui2{" +
                "age=" + age +
                '}';
    }
}`

泛型

有两层意思,先指定类型,后续代码根据类型编写代码,类型不符,在编译期就会报错

  • 二、自定义泛型,先写一个“空类型”,如“t”、或者其他任意字符,再在使用时,具体指定类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值