Java集合框架

1、集合的理解好处

  • 数组
  1. 长度开始必须指定,而且一旦指定,不能更改
  2. 保存的必须为同一类型的元素
  3. 使用数组进行增加/删除元素比较麻烦
  • 集合
  1. 可以动态保存任意多个对象,使用比较方便
  2. 提供了一系列方便的操作对象的方法:add、remove、set、get等
  3. 使用集合添加,删除新元素简洁了

2、集合框架体系图

  1. Collection(单列集合:List、Set)
    在这里插入图片描述
  2. Map(双列集合:k、v键值对)
    在这里插入图片描述

2.1、Collection接口和常用方法

  1. Collection接口实现类的特点
public interface Collection<E> extends  Iterable<E>
  • Collection实现子类可以存放多个元素,每个元素可以是Object
  • 有些Collection的实现类,可以存放重复的元素
  • 有些Collection的实现类,有些是有序的(List),有些是无序的(Set)
  • Collection接口没有直接的实现子类,是通过它的子接口Set和List来实现的
  • Collection接口遍历元素方式-使用Iterator(迭代器)
  1. Collection接口和常用方法(以实现类ArrayList为例)
    1. add:添加单个元素
    2. remove:删除指定元素
    3. contains:查找元素是否存在
    4. size:获取元素的个数
    5. isEmpty:判断是否为空
    6. clear:清空
    7. addAll:添加多个元素
    8. containsAll:查找多个元素是否都存在
    9. removeAll:删除多个元素
		List list = new ArrayList();

        //add:添加单个元素
        list.add("jack");
        list.add(10);
        list.add(true);

        //remove:删除指定元素
        list.remove("jack");//指定删除某个元素
        list.remove(0);//删除索引第一个元素

        //contains:查找元素是否存在
        list.contains("jack");

        //addAll:添加多个元素
        List list1 = new ArrayList();
        list1.add("qw");
        list1.add("qq");
        list.addAll(list1);
  1. 用迭代器和增强for循环两种方式来遍历
public class Collection练习 {
    public static void main(String[] args) {
        List list = new ArrayList();
        list.add(new Dog("小黑",3));

        //增强for
        for (Object dog:list) {
            System.out.println(dog);
        }
        //使用迭代器
        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            Object dog =  iterator.next();
            System.out.println(dog);
        }

    }
}
class Dog{
    private String name;
    private int age;

2.2、List接口和常用方法

  • List接口的基本介绍
  1. List接口是Collection接口的子接口
  2. Lsit集合类中元素有序(即添加顺序和取出顺序一致),且可重复
  3. List集合中每个元素都有其对应的顺序索引,即支持索引
  • List接口常用方法
		List list = new ArrayList();
        list.add("小明");
        list.add("小黑");

        //add(int index) :在index的位置插入一个对象
        list.add(1,"小红");
        System.out.println(list);   //[小明, 小红, 小黑]

        //addAll(int index ,Collection con) :从index位置开始将con中的元素添加进来
        List list2 = new ArrayList();
        list2.add("jack");
        list2.add("tom");
        list.addAll(1,list2);
        System.out.println(list);   //[小明, jack, tom, 小红, 小黑]

        //get ;获取指定index位置的元素

        //indexOf(Object obj) :返回obj在集合中首次出现的位置
        System.out.println(list.indexOf("tom"));    //2

        //lastIndexOf(Object obj):返回obj在集合中末次出现的位置
        list.add("小明");
        System.out.println(list);   //[小明, jack, tom, 小红, 小黑, 小明]
        System.out.println(list.lastIndexOf("小明")); //5

        //remove(int index):移除指定index位置的元素,并返回此元素
        System.out.println(list.remove(5)); //小明

        //set(int index,Object obj):设置指定index位置元素为obj,相当于是替换或者修改
        list.set(2,"玛丽");
        System.out.println(list);   //[小明, jack, 玛丽, 小红, 小黑]

        //subList(int fromIndex,int toIndex):返回从fromIndex到toIndex位置的子集合
        List list1 = list.subList(0, 3);
        System.out.println(list1);  //[小明, jack, 玛丽]
    }
  • List接口练习1
    • 添加几个元素,在2号位插入一个元素,获得第五个元素,删除第六个元素,修改第七个元素,再使用迭代器遍历集合
    • 要求,使用List的实现类ArrayList完成
public class List练习 {
    public static void main(String[] args) {
        List list = new ArrayList();
        for (int i = 0; i < 12; i++) {
            list.add("hello"+i);
        }
        list.add(1,"你是谁");
        list.get(4);
        list.remove(5);
        list.set(6,"修改");

        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            Object obj =  iterator.next();
            System.out.println(obj);
        }

    }
}
  • List接口练习2
    • 使用List的实现类添加三本书,并遍历
    • 要求:
      • 按价格排序,从低到高(使用冒泡法)
      • 要求使用ArrayList、LinkedList和Vector三种集合实现
public class List练习2 {
    public static void main(String[] args) {
        List list = new ArrayList();
        //List list1 = new Vector();
        //List list2 = new LinkedList();
        list.add(new Book("红楼梦","曹雪芹",100));
        list.add(new Book("红楼","曹雪",10));
        list.add(new Book("红","曹",10));

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

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

    }
    public static void sort(List list){
        for (int i = 0; i < list.size()-1; i++) {
            for (int j = 0; j < list.size()-1-i; j++) {
                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);
                }
            }
        }
    }
}
class Book{
    private String name;
    private String author;
    private double price;

2.2.1、ArrayList

  1. ArrayList 可以加入null,并且可以加入多个
  2. ArrayList是由数组(可变数组)实现数据存储的
  3. ArrayList基本等同于Vector,除了ArrayList是线程不安全(执行效率高),在多线程情况下,不建议使用ArrayList
  4. ArrayList增删效率低,查改的效率高
ArrayList arrayList = new ArrayList();
        arrayList.add(null);
        arrayList.add("jack");
        arrayList.add(null);
        System.out.println(arrayList);  //[null, jack, null]
  1. 当创建ArrayList对象时,如果使用的是无参构造,则初始数组容量为0,第1次添加,则扩容数组为10,如果需要再次扩容,则扩容数组的1.5倍
  2. 如果使用的是指定大小的构造器,则初始数组容量为指定大小,如果需要扩容,则直接扩容数组的1.5倍

2.2.2、Vector

  1. Vector底层也是一个对象数组
  2. Vector是由数组(可变数组)实现数据存储的
  3. Vector是线程同步的,即线程安全(执行效率低),Vector类的操作方法带有synchronized
  4. 在开发中,需要线程同步安全时,考虑使用Vector
public synchronized E get(int index) {
        if (index >= elementCount)
            throw new ArrayIndexOutOfBoundsException(index);

        return elementData(index);
    }
  1. 当创建Vector对象时,如果使用的是无参构造,则默认数组容量为10,满后,就按照2倍扩容
  2. 如果使用的是指定大小的构造器,则初始数组容量为指定大小,如果需要扩容,则直接按2倍扩容

2.2.3、LinkedList

  1. LinkedList实现了双向链表和双端队列特点
  2. 可以添加任意元素(元素可以重复),包括null
  3. 线程不安全,没有实现同步
  4. LinkedList底层维护了一个双向链表
  5. LinkedList中维护了两个属性first和last分别指向首节点和为节点
  6. 每个节点(Node对象),里面又维护了prev、next、item三个属性,其中通过prev指向前一个,通过next指向后一个节点,最终实现双向链表
  7. 所有LinkedList的元素的添加和删除,不是通过数组完成的,相对来说效率较高
  8. LinkedList增删效率高,查改的效率低
package com.han;

public class LinkedList {
    public static void main(String[] args) {
        //模拟一个简单的双向链表
        Node jack = new Node("jack");
        Node tom = new Node("tom");
        Node make = new Node("make");

        //连接三个节点,形成双向链表
        //jack->tom->make
        jack.next=tom;
        tom.next=make;
        //make->tom->jack
        make.pre=tom;
        tom.pre=jack;

        Node first=jack;//头节点
        Node last=make;//尾节点

        //从头到尾的遍历
        while (true){
            if (first==null){
                break;
            }
            System.out.println(first);  //jack/ntom/nmake
            first=first.next;
        }

        //从尾到头的遍历
        while (true){
            if (last==null){
                break;
            }
            System.out.println(last);   //make/ntom/njack
            last=last.pre;
        }

        //链表添加一个数据
        //在tom和make之间插入一个smith
        Node smith = new Node("smith");
        smith.pre=tom;
        smith.next=make;
        tom.next=smith;
        make.pre=smith;

        first=jack;
        while (true){
            if (first==null){
                break;
            }
            System.out.println(first);  //jack/ntom/nsmith/nmake
            first=first.next;
        }

    }
}
//定义一个Node类,Node对象,表示双向链表的一个节点
class Node{
    public Object item; //真正存放数据
    public Node next;   //指向后一个节点
    public Node pre;    //指向前一个节点

    public Node(Object name) {
        this.item = name;
    }

    @Override
    public String toString() {
        return "Node name=" +item;
    }
}


2.3、Set接口和常用方法

  • 无序,没有索引
  • 不允许重复元素,所以最多包含一个null
  • 和List接口一样,Set接口也是Collection的子接口,因此,常用方法和Collection接口一样
  • Set接口的遍历方式:1.可以使用迭代器 2. 增强for 3. 不能使用索引的方式来获取
  • Set接口对象,不能通过索引来获取,即不能通过普通for循环遍历
		Set set = new HashSet();
        set.add("join");
        set.add("lusy");
        set.add("jack");
        set.add("join");//再次添加相同元素
        set.add(null);
        set.add(null);//再次添加null
        System.out.println(set);    //[null, join, lusy, jack]

        //遍历方式1:迭代器
        Iterator iterator = set.iterator();
        while (iterator.hasNext()) {
            Object obj = iterator.next();
            System.out.print(obj+" ");  //null join lusy jack
        }
        //遍历方式2:增强for
        for (Object o :set) {
            System.out.print(o+" ");    //null join lusy jack
        }

2.3.1、HashSet(数组+单向链表

  • HashSet底层是HashMap,HashMap底层是(数组+链表+红黑树)
        set=new HashSet();
        System.out.println(set);    //[]
        set.add("lusy");//添加成功
        set.add("lusy");//加入不了
        set.add(new Dog1("tom"));//ok
        set.add(new Dog1("tom"));//ok
        System.out.println(set);    //[com.han.Dog1@4554617c, com.han.Dog1@1b6d3586, lusy]

        //底层机制
        set.add(new String("hsp"));//ok
        set.add(new String("hsp"));//加入不了
        System.out.println(set);    //[hsp, com.han.Dog1@4554617c, com.han.Dog1@1b6d3586, lusy]
    }
}
class Dog1{
    private String name;

2.3.2、LinkedHashSet

  • LinkedHashSet是HashSet的子类
  • LinkedHashSet底层是一个LinkedHashMap,底层维护了一个数组+双向链表
  • LinkedHashSet根据元素的hashCode值来决定元素的存储位置
  • LinkedHashSet不允许添加重复元素

3、Map接口和常用方法

  • Map与Collection并列存在,用于保存具有映射关系的数据:Key-Value
  • Map中的key和value可以是任何引用类型的数据,会封装到HashMap$Node对象中
  • Map中的key不允许重复
  • Map中的value可以重复
  • Map的key可以为null,value也可以为null,注意 key为null,只能有一个,value为null,可以有多个
  • 常用String类作为Map的key
  • key和value之间存在单向一对一关系,即通过指定的key总能找到对应的value
  • Map接口的常用方法
  1. put:添加
  2. remove:根据键删除映射关系
  3. get:根据键获取值
  4. size:获取元素个数
  5. isEmpty:判断 个数是否为0
  6. clear:清除
  7. containsKey:查找键是否存在
		Map map1 = new HashMap();
        map1.put("q","qq");
        map1.put("a",null);
        map1.put(null,"b");
        System.out.println(map1);   //{null=b, q=qq, a=null}

        System.out.println(map1.remove(null));//b
        System.out.println(map1.get("a"));//null
        System.out.println(map1.size());//2
        System.out.println(map1.isEmpty());//false
        System.out.println(map1.containsKey("q"));//true
  • Map接口的遍历
		//第一组:取出所有的key,通过key取出对应的Value
		Set keySet = map1.keySet();
        //(1)增强for
        for (Object key :keySet) {
            System.out.print(key+"-"+map1.get(key)+" ");    //q-qq a-null
        }
        //(2)迭代器
        Iterator iterator = keySet.iterator();
        while (iterator.hasNext()) {
            Object key = iterator.next();
            System.out.print(key+"-"+map1.get(key)+" ");    //q-qq a-null
        }

		//第二组:把所有的value值取出
		Collection values = map1.values();
        //1.增强for
        for (Object value :values) {
            System.out.println(value);  //qq  null
        }
        //2.迭代器
        Iterator iterator1 = values.iterator();
        while (iterator1.hasNext()) {
            Object value = iterator1.next();
            System.out.println(value);  //qq  null
        }
        //第三组:通过EntrySet 来获取 k-v
        Set entrySet = map1.entrySet();
        //1.增强for
        for (Object entry :entrySet) {
            Map.Entry m =(Map.Entry) entry;
            System.out.println(m.getKey()+"-"+m.getValue());    //q-qq  a-null
        }
        //2.迭代器
        Iterator iterator2 = entrySet.iterator();
        while (iterator2.hasNext()) {
            Object next = iterator2.next();
            System.out.println(next);   //q=qq  a=null
        }

3.1、HashMap

  • Map接口的常用实现类:HashMap、Hashtable、Properties
  • HashMap是Map接口使用频率最高的实现类
  • HashMap是以key-value对的方式来存储数据的
  • key不能重复,但是值可以重复,允许使用null键和null值
  • 如果添加相同的key,则会覆盖原来的key-value,等同于修改(key不会替换,value会替换)
  • 与HashSet一样,不保证映射的顺序,因为底层是以hash表的方式来存储的(数组+链表+红黑树)
  • HashMap没有实现同步,因此是线程不安全
    扩容机制:
    在这里插入图片描述

3.2、HashTable

  • 存放的元素是键值对:k-v
  • HashTable的键 和值都不能为null,否则会抛出NullPointerException
  • HashTable使用方法基本和HashMap一样
  • HashTable是线程安全的,HashMap是线程不安全的

3.3、Map接口实现类-Properties

  • Properties类继承自HashTable类并且实现了Map接口,也是使用一种键值对形式来保存数据
  • 它的使用特点和HashTable类似
  • 它的键 和值都不能为null
  • Properties还可以用于从xxx.properties文件中,加载数据到Properties类对象,并进行读取和修改
  • 工作后:xxx.properties文件通常作为配置文件

如何选择集合实现类
在这里插入图片描述

4、编程题

  • 第一题:
    在这里插入图片描述
public class homework01 {
    public static void main(String[] args) {
        ArrayList arrayList = new ArrayList();
        arrayList.add(new News("新冠肺炎病例超千万"));
        arrayList.add(new News("男子突然想起两个月前钓的鱼还在网兜里"));
        for (int i = arrayList.size()-1; i >=0; i--) {
            //System.out.println(arrayList.get(i));
            News news =(News) arrayList.get(i);
            System.out.println(processTitle(news.getTitle()));
        }
    }
    public static String processTitle(String title){
        if (title==null){
            return "";
        }
        if (title.length()>15){
            return title.substring(0,15)+"...";
        }else {
            return title;
        }
    }

}
class News{
    private String title;
    private String content;

    public News(String title) {
        this.title = title;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    @Override
    public String toString() {
        return "News{" +
                "title='" + title + '\'' +
                '}';
    }
}
  • 第二题:
    在这里插入图片描述
		Map map = new HashMap();
        map.put("jack",650);    //int->Integer
        map.put("tom",1200);    //int->Integer
        map.put("smith",2900);    //int->Integer

        map.put("jack",2600);//替换

        Set keySet = map.keySet();
        for (Object key :keySet) {
            map.put(key,(Integer)map.get(key)+100);
        }
        System.out.println(map);

        //遍历
        Set entrySet = map.entrySet();
        Iterator iterator = entrySet.iterator();
        while (iterator.hasNext()) {
            Map.Entry entry =(Map.Entry)  iterator.next();
            System.out.println(entry.getKey()+"-"+entry.getValue());
            
        }

        //遍历工资
        Collection values = map.values();
        for (Object value :values) {
            System.out.println(value);
        }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值