java中的集合

一、基本概念

1.可以动态保存任意多个对象,使用方便

2.提供了一系列方便操作对象的方法:add、remove、set、get等

3.使用集合添加,删除新元素的代码简洁

(1)、集合的框架体系

java的集合类很多,主要分为两大类:Collection和Map。

1.集合主要是两组(单列集合,双列集合)

2.Collection接口有两个重要的子接口,List和Set,它们的实现子类都是单列集合

3.Map接口的实现子类是双列集合,存放的K-V

 二、Collection接口

(1)、常用方法

(1)Collection实现子类可以存放多个元素,每个元素可以是Object

(2)Collection的有些实现类,可以存放重复的元素,有些不可以

(3)Collection的有些实现类,有些是有序的(List),有些不是有序(Set)

(4)Collection接口没有直接的实现子类,是通过它的子接口Set 和 List 来实现的

 以下代码演示Collection实现类的常用方法

import java.util.ArrayList;
import java.util.List;


public class CollectionMethod {
    @SuppressWarnings({"all"})
    public static void main(String[] args) {
        List list = new ArrayList();
//        1.add:添加单个元素
        list.add("jack");
        list.add(10);//list.add(new Integer(10))
        list.add(true);
        System.out.println("list=" + list);
//        2.remove:删除指定元素
        //list.remove(0);//删除第一个元素
        list.remove(true);//指定删除某个元素
        System.out.println("list=" + list);
//        3.contains:查找元素是否存在
        System.out.println(list.contains("jack"));//T
//        4.size:获取元素个数
        System.out.println(list.size());//2
//        5.isEmpty:判断是否为空
        System.out.println(list.isEmpty());//F
//        6.clear:清空
        list.clear();
        System.out.println("list=" + list);
//       7. addAll:添加多个元素
        ArrayList list2 = new ArrayList();
        list2.add("红楼梦");
        list2.add("三国演义");
        list.addAll(list2);
        System.out.println("list=" + list);
//        8.containsAll:查找多个元素是否都存在
        System.out.println(list.containsAll(list2));//T
//        9.removeAll:删除多个元素
        list.add("聊斋");
        list.removeAll(list2);
        System.out.println("list=" + list);//[聊斋]
//        说明:以ArrayList实现类来演示.

    }
}

(2)、Collection接口遍历元素方式

1.Iterator迭代器

Iterator对象称为迭代器,主要用于遍历Collection集合中的元素。

所有实现了Collection接口的集合类都有一个itertor()方法,用以返回一个实现了Iterator接口的对象,即可以返回一个迭代器。

Iterator仅用于遍历结合,Iterator本身并不存放对象。

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;


public class CollectionIterator {
    @SuppressWarnings({"all"})
    public static void main(String[] args) {

        Collection col = new ArrayList();

        col.add(new Book("三国演义", "罗贯中", 10.1));
        col.add(new Book("小李飞刀", "古龙", 5.1));
        col.add(new Book("红楼梦", "曹雪芹", 34.6));
        
        //1. 先得到 col 对应的 迭代器
        Iterator iterator = col.iterator();
        //2. 使用while循环遍历
        while (iterator.hasNext()) {//判断是否还有数据
            //返回下一个元素,类型是Object
            Object obj = iterator.next();
            System.out.println("obj=" + obj);
        }
        //快捷键,快速生成 while => itit
        //显示所有的快捷键的的快捷键 ctrl + j
        
        //3. 当退出while循环后 , 这时iterator迭代器,指向最后的元素
        //4. 如果希望再次遍历,需要重置我们的迭代器
        iterator = col.iterator();
        System.out.println("===第二次遍历===");
        while (iterator.hasNext()) {
            Object obj = iterator.next();
            System.out.println("obj=" + obj);
        }

    }
}

class Book {
    private String name;
    private String author;
    private double price;

    public Book(String name, String author, double price) {
        this.name = name;
        this.author = author;
        this.price = price;
    }

    public String getName() {
        return name;
    }

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

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

    @Override
    public String toString() {
        return "Book{" +
                "name='" + name + '\'' +
                ", author='" + author + '\'' +
                ", price=" + price +
                '}';
    }
}

 2、增强for循环

 增强for循环,可以代替iterator选代器,特点:增强for就是简化版的iterator本质一样。只能用于遍历集合或数组。
基本语法
for(元素类型 元素名:集合名或数组名){

        访问元素

}
for (object object : col){

        System.out.printin(object);

}

遍历时,每个元素都是Object类型

for (Object o : col) {
    System.out.println("book=" + o);
}

 三、List接口和常用方法

(1)List 接口是 Collection 接囗的子接口 

(2)List集合类中元素有序(即添加顺序和取出顺序一致)、且可重复

(3)List集合中的每个元素都有其对应的顺序索引,即支持索引。

(4)List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。

常用的有:AyyayList、LinkedList和Vector

 (1).List接口的常用方法

import java.util.ArrayList;
import java.util.List;
public class ListMethod {
    @SuppressWarnings({"all"})
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add("张三丰");
        list.add("贾宝玉");
//        1.void add(int index, Object ele):在index位置插入ele元素
        //在index = 1的位置插入一个对象
        list.add(1, "韩顺平");
        System.out.println("list=" + list);
//        2.boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来
        List list2 = new ArrayList();
        list2.add("jack");
        list2.add("tom");
        list.addAll(1, list2);
        System.out.println("list=" + list);
//        3.Object get(int index):获取指定index位置的元素

//        int indexOf(Object obj):返回obj在集合中首次出现的位置
        System.out.println(list.indexOf("tom"));//2
//        int lastIndexOf(Object obj):返回obj在当前集合中末次出现的位置
        list.add("韩顺平");
        System.out.println("list=" + list);
        System.out.println(list.lastIndexOf("韩顺平"));
//        Object remove(int index):移除指定index位置的元素,并返回此元素
        list.remove(0);
        System.out.println("list=" + list);
//        Object set(int index, Object ele):设置指定index位置的元素为ele , 相当于是替换.
        list.set(1, "玛丽");
        System.out.println("list=" + list);
//        List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的子集合
        // 注意返回的子集合 fromIndex <= subList < toIndex
        List returnlist = list.subList(0, 2);
        System.out.println("returnlist=" + returnlist);

    }
}

 (2).List的三种遍历方式

方式一:使用iterator

Iterator iter = col.iterator();

while(iter.hasNext()){                                                                                                                         Object o = iter.next();

}
2)方式二:使用增强forfor(object o:col){

}
3)方式三:使用普通forforint i=0;i<list.size();i+ +){

        Object object = list.get(i);

        System.out.println(object);

}
说明:使用LinkedList完成 使用方式和ArrayList 一样

import java.util.*;

public class ListFor {
    @SuppressWarnings({"all"})
    public static void main(String[] args) {
        //List 接口的实现子类 Vector LinkedList
        //List list = new ArrayList();
        //List list = new Vector();
        List list = new LinkedList();

        list.add("jack");
        list.add("tom");
        list.add("鱼香肉丝");
        list.add("北京烤鸭子");

        //遍历
        //1. 迭代器
        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            Object obj =  iterator.next();
            System.out.println(obj);
        }
        System.out.println("=====增强for=====");

        //2. 增强for
        for (Object o : list) {
            System.out.println("o=" + o);
        }
        System.out.println("=====普通for====");

        //3. 使用普通for
        for (int i = 0; i < list.size(); i++) {
            System.out.println("对象=" + list.get(i));

        }
    }
}

 例题:使用List的实现类添加三本图书,并按照价格排序,从低到高(使用冒泡排序)

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Vector;


@SuppressWarnings({"all"})
public class ListExercise02 {

    public static void main(String[] args) {

        //List list = new ArrayList();
        List list = new LinkedList();
        //List list = new Vector();
        list.add(new Book("红楼梦", "曹雪芹", 100));
        list.add(new Book("西游记", "吴承恩", 10));
        list.add(new Book("水浒传", "施耐庵", 19));
        list.add(new Book("三国", "罗贯中", 80));

        //冒泡排序
        sort(list);

        System.out.println("==排序后==");

        for (Object o : list) {
            System.out.println(o);
        }

    }

    //静态方法
    //价格要求是从小到大
    public static void sort(List list) {

        int listSize = list.size();
        for (int i = 0; i < listSize - 1; i++) {
            for (int j = 0; j < listSize - 1 - i; j++) {
                //取出对象Book,
                //取出的是Object类型,需要强制类型转化为Book类型
                Book book1 = (Book) list.get(j);
                Book book2 = (Book) list.get(j + 1);
                if (book1.getPrice() > book2.getPrice()) {//交换
                    list.set(j, book2);
                    list.set(j + 1, book1);
                }
            }
        }

    }
}

***上述代码中的Book类型可以查看上面迭代器展示时的代码示例中的Book类型

(3)ArrayList底层结构和源码分析

1.ArrayList的注意事项

(1)permits all elements, including null ,ArrayList 可以加入null,并且多个

(2)ArrayList 是由数组来实现数据存储的

(3)ArrayList 基本等同于Vector,除了 ArrayList是线程不安全(执行效率高) 看源码在多线程情况下,不建议使用ArrayList

2.ArrayList的底层操作机制

(1)ArrayList中维护了一个Object类型的数组elementData

transient Object[l elementData; //transient 表示瞬间,短暂的, 表示该属性不会被序列号

(2)当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第1次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍。
3)如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容则直接扩容elementData为1.5倍。

源代码演示扩容机制

 (4)Vector的底层操作机制

1.Vector底层也是一个对象数组,

2.Vector是线程同步的,即线程安全的,Vector类的操作方法带有synchronized

3.在开发中,需要线程同步安全时,考虑使用Vector

(5)Vector和ArrayList的比较

(6)LinkedList底层结构

(1)LinkedList底层实现了双向链表和双端队列特点

(2)可以添加任意元素(元素可以重复),包括null

(3)线程不安全,没有实现同步

(4)LinkedList底层维护了一个双向链表,

(5)LinkedList中维护了两个属性first和last分别指向 首节点和尾节点

(6)每个节点(Node对象),里面又维护了prev、next、item三个属性,其中通过prev指向前一 个,通过next指向后一个节点。最终实现双向链表.

(7)所以LinkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高。5)模拟一个简单的双向链表

 LinkedList的增删查改

import java.util.Iterator;
import java.util.LinkedList;
@SuppressWarnings({"all"})
public class LinkedListCRUD {
    public static void main(String[] args) {

        LinkedList linkedList = new LinkedList();
        linkedList.add(1);
        linkedList.add(2);
        linkedList.add(3);
        System.out.println("linkedList=" + linkedList);

        //演示一个删除结点的
        linkedList.remove(); // 这里默认删除的是第一个结点
        //linkedList.remove(2);

        System.out.println("linkedList=" + linkedList);

        //修改某个结点对象
        linkedList.set(1, 999);
        System.out.println("linkedList=" + linkedList);

        //得到某个结点对象
        //get(1) 是得到双向链表的第二个对象
        Object o = linkedList.get(1);
        System.out.println(o);//999

        //因为LinkedList 是 实现了List接口, 遍历方式
        System.out.println("===LinkeList遍历迭代器====");
        Iterator iterator = linkedList.iterator();
        while (iterator.hasNext()) {
            Object next = iterator.next();
            System.out.println("next=" + next);
        }

        System.out.println("===LinkeList遍历增强for====");
        for (Object o1 : linkedList) {
            System.out.println("o1=" + o1);
        }
        System.out.println("===LinkeList遍历普通for====");
        for (int i = 0; i < linkedList.size(); i++) {
            System.out.println(linkedList.get(i));
        }
    }
}

 (7)ArrayList和LinkedList的比较分析

 四、Set接口和常用方法

(1)Set接口基本介绍

1.无序(添加和取出的顺序不一致),没有索引

2不允许重复元素,所以最多包含一个null

3.和List接口一样,Set接口也是Collection的子接口,因此常用方法和Collection接口一样

4.取出Set时,取出的顺序虽然不是添加的顺序,但也是固定的顺序(即多次取出的顺序是一致的)

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

@SuppressWarnings({"all"})
public class SetMethod {
    public static void main(String[] args) {
        //老韩解读
        //1. 以Set 接口的实现类 HashSet 来讲解Set 接口的方法
        //2. set 接口的实现类的对象(Set接口对象), 不能存放重复的元素, 可以添加一个null
        //3. set 接口对象存放数据是无序(即添加的顺序和取出的顺序不一致)
        //4. 注意:取出的顺序的顺序虽然不是添加的顺序,但是他的固定.
        Set set = new HashSet();
        set.add("john");
        set.add("lucy");
        set.add("john");//重复
        set.add("jack");
        set.add("mary");
        set.add(null);//
        set.add(null);//再次添加null
        for(int i = 0; i <10;i ++) {
            System.out.println("set=" + set);
        }

        //遍历
        //方式1: 使用迭代器
        System.out.println("=====使用迭代器====");
        Iterator iterator = set.iterator();
        while (iterator.hasNext()) {
            Object obj =  iterator.next();
            System.out.println("obj=" + obj);
        }

        set.remove(null);

        //方式2: 增强for
        System.out.println("=====增强for====");

        for (Object o : set) {
            System.out.println("o=" + o);
        }
        //set 接口对象,不能通过索引来获取
    }
}

 (2)HashSet的全面说明

(1)HashSet实现了Set接口
(2)Hashset实际上是HashMap,
public Hashset(){map = new HashMap<>();
(3)可以存放null值,但是只能有一个null
(4) HashSet不保证元素是有序的,取决于hash后,再确定索引的结果。(即,不保证存放元素的顺序和取出顺序一致)

(5)不能有重复元素/对象.在前面Set 接口使用已经讲过

(3)HashSet的底层机制

1HashSet 底层是 HashMap

2.添加一个元素时,先得到hash值 -会转成->索引值

3.找到存储数据表table,看这个索引位置是否已经存放的有元素

4.如果没有,直接加入

5.如果有 ,调用 equals 比较,如果相同,就放弃添加,如果不相同,则添加到最后

6.在Java8中,如果一条链表的元素个数到达 TREEIFY_THRESHOLD(默认是8),并且table的大小>=MIN_TREEIFY_CAPACITY(默认64),就会进行树化(红黑树)

7.HashSet底层是HashMap,第一次添加时,table 数组扩容到 16,1临界值(threshold)是 16*加载因子(loadFactor)是0.75=12

8.如果table 数组使用到了临界值 12,就会扩容到 16*2=32,新的临界值就是32*0.75 =24,依次类推

9.在Java8中,如果一条链表的元素个数到达 TREEIFY THRESHOLD(默认是 8),并且table的大小 >=MIN TREEIFY CAPACITY(默认64),就会进行树化(红黑树),否则仍然采用数组扩容机制

以上内容为集合中的部分内容,后续内容会在接下来的博客中继续更新

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值