集合框架

Java集合总结

一.集合概述

由于数组长度固定,当添加的元素超过了数组的长度时,需要对数组重新定义,故Java提供集合,能储存任意对象,随着元素的改变而改变。

数组和集合的区别:

1>.数组既可以存储基本数据类型,又可以储存引用数据类型,基本数据类型储存的是值,引用数据类型储存的是地址值。集合只能储存引用数据类型,集合在存储基本数据类型的时会自动装箱变成对象,故集合只能存储引用数据类型。

2>.数组的长度是固定,不能自动增长;而集合的长度是可变的,根据元素的改变而改变。

二.集合框架

在这里插入图片描述

Java的集合大致可以分为四个体系,Set,List,Map,Queue;Set代表无序,不可重复的集合;List代表有序,重复的集合;Map代表具有映射关系的集合,Queue代表一种队列集合的体现。

三.Collection体系(单向)

Set与List接口是Collection接口派生的两个子接口,故Collection具有的方法两者均含有。
1.方法:(不带All)

boolean add (E,e) //添加元素,如果集合对象被添加操作改变了则返回true
boolean remove(Object o) //删除指定元素,当集合中包含一个或多个元素被删除,该方法将返回true
void clear() //清空集合,使集合长度变为0.
boolean contains(Object o) //查看集合里是否包含指定元素
boolean isEmpty() //判断是否为空,长度为0时返回true,否则返回false
int size //获取集合中元素的个数

add方法如果是List集合,会一直返回true,因为List集合是可以储存重复元素的,而如果是set集合,当储存重复元素是会返回false

带All:

举个栗子

public static void main(String[] args)
{
        Collection c1=new ArrayList();
        c1.add("a");
        c1.add("b");
        c1.add("c");
        c1.add("d");

        Collection c2=new ArrayList();
        c2.add("a");
        c2.add("b");

        boolean b1=c1.removeAll(c2)//删除的是交集
       // boolean b1=c1.containsAll(c2)//判断调用的集合是否包含传入的集合
       // boolean b1=c1.retainAll(c2);//取交集,如果调用的c1集合改变就返回true,不变就返回false

        System.out.println(b1);
        c1.addAll(c2);//将c2添加到c1中,输出结果是[a,b,c,d,a,b]
       // c1.add(c2);//将c2当成一个元素添加到c1中,输出结果是[a,b,c,d,[a,b]]
        System.out.println(c1);
    }

2.集合的遍历:依次获取集合中的每一个元素。

法一:利用for循环遍历
 代码如下

public static void main(String[] args)
{
        Collection c=new ArrayList();
        c.add("a");
        c.add("b");
        c.add("c");
        c.add("d");
        /*转化成数组遍历*/
        Object[] arr = c.toArray();//将集合转化成数组
        int i;
        for(i=0;i<arr.length;i++)
        {
            System.out.println(arr[i]);
        }
 }

法二:迭代(遍历)

举个栗子

public static  void main(String[] args)
{
        Collection c=new ArrayList();
        c.add("a");
        c.add("b");
        c.add("c");
        c.add("d");
        /*对集合中的元素迭代*/
        Iterator it = c.iterator();//获取迭代器
        while(it.hasNext())//判断集合中是否有元素,有就返回true
        {
            System.out.println(it.next());//相当于指针,每次向后移动一个
        }
 }

四.List

List中特有的方法

void add(int index,Object element);//在指定位置添加元素
boolean addAll(int index,Collection c);//将集合中c所包含的所有元素都插在List集合的index处
remove(int index);//通过索引删除元素,并返回剩余的元素
get(int index);//通过索引获取元素
set(int index,Object element);//修改指定位置的元素返回新元素

 除过iterator()f方法外,List还提供了一个listIterator()方法,该方法返回一个listIterator(),继承了Iterator接口。
举个栗子:

public static void main(String[] args)
    {
        List list =new ArrayList();//父类引用指向子类对象
        list.add("a");
        list.add("b");
        list.add("world");
        list.add("c");
        list.add("d");
        list.add("e");
        ListIterator lit =list.listIterator();
        while(lit.hasNext())
        {
            String str=(String)lit.next();
            if("world".equals(str))
            {
                lit.add("javaee");
            }
        }
        System.out.println(list);
    }

在原基础上,ListIterator还增加了如下方法

Boolean hasPrevious()//返回该迭代器关联的集合是否还有上一个元素
Object previous()//返回迭代器的上一个元素
void add()//在指定位置插入一个元素

例如:

 ListIterator lit =list.listIterator();
 while(lit.hasNext)//正向遍历
 {
 	System.out.println(lit.next());
 }
 while(lit.hasPrevious())//逆向遍历
 {
 	System.out.println(lit.previous());
 }

逆向遍历必须与正向遍历配套使用,因为,逆向遍历是指针向前移动,只使用逆向遍历时,会指向首元素的前一个位置,由于未储存元素,所以循环不会进行,即无法遍历

(一).ArrayList与Vector(数组实现)

 这两个的用法基本一样,后者已经被前者替代。Vector较为古老,方法名较长,Java改写了其中的方法,除此之外,Vector还有许多缺点,通常尽量少用Vector。

ArrayList与Vector的显著区别:
ArrayList的线程不安全,但效率高;而Vector的线程比较安全,但其效率较低

(二).LinkedList(链表实现)

特有的方法:

void addFirst(Object e)addLast(Object e)//添加第一个,最后一个
getFirst()getLast()//得到第一个,最后一个
removeFirst()removeLast()//删除第一个,最后一个
get(int index)//找到索引的元素

小结:
List的三个子类的特点:

ArrayList :底层数据结构是数组,查询快,增删慢。线程不安全,效率高。
Vector:底层数据结构是数组,查询快,增删慢。线程安全,效率高。
LinkList:底层数据结构是链表,查询慢,增删快。线程不安全,效率高。

查询多,用ArrayList;增删多,用LinkedList。

五.Set接口

Set集合与Collection基本完全一样,没有提供额外的方法,实际上Set就是Collection,只是行为不同(Set不允许包含重复元素)

Set中比较元素是否相等不是使用运算符==,而是equals进行判断,如果两个元素相等,就会返回true,Set则就不会再添加该元素,若为false则会添加

(一).HashSet类

HashSet是按照Hash算法来储存集合中的元素,故具有很好的存取和查找功能。

1.HashSet的特点

1>.不能保证元素的排列顺序,顺序有可能发生变化。
2>.集合元素值可以是null。

2.存储不会出现重复元素的原因:

当向HasSet集合中储存元素时,它会调用hashCode()方法来得到该对象的hashCode值,然后根据HashCode的值来来决定该对象在HashCode中储存的位置。如果两个元素通过equals方法比较返回true,但他们的hashCode()方法返回值不同,HashSet将会把他们储存在不同位置,也可以添加成功。

简单来说,判断的标准是两个对象通过equals方法比较相等,并且对象的hashCode值返回也相等

3.hashCode方法重写方式
 Java中如果hashCode的返回值相等,但equals的返回值为false,这时在“桶”里放多个元素,(HashSet中能储存元素的槽位,通常称为“桶”)这会导致性能下降。
 重写基本规则:

对象内每个有意义的属性f(即每个用作equals()比较标准的属性)计算出一个int类型的hashCode值

用计算出来的多个hashCode组合计算出一个hsahCode值返回。
栗子:
return f1.hashCode() + (int)f2;
 为了直接避免相加产生偶然相等,可以通过各属性乘任意一个质数,再相加。
栗子:
return f1.hashCode()*31+(int)f2*31

也可以对equals方法进行重写

补充:linkedHashSet

特点

底层是链表实现的,是Set集合中唯一一个能保证怎么存就怎么取的集合对象
因为是HashSet的子类,所以也是保证元素唯一的,与HashSet的原理一样

(二)TreeSet:

特有方法:

Comparator comparator():返回当前Set使用的Comparator,或者返回null,表示以自然方式排序
Object first():返回集合中的第一个元素
Object last():返回集合中的最末一个元素
Object lower(Object e):返回集合中位于指定元素之前的元素
Object higher(Object e):返回集合中位于指定元素之后的元素

 可以保证集合元素处于排序状态的机制
举个栗子:
在这里插入图片描述
由上的结果可以看出,TreeSet并不是根据元素的插入顺序进行排序,而是根据元素的实际值进行排序,采用二叉树进行排序,支持两种排序方式:自然排序和定制排序,默认情况下支持自然排序。

二叉树:小的储存在左边(负数),大的储存在右边(正数),相等就不存(0),在TreeSet集合中,如何储存元素取决于compareTo方法的返回值

六.Map(映射,双向)

 Map用于保存具有映射关系的数据,因此Map集合里保存着两组值,一组值用于保存Map里的key,另一组值用于保存Map里的value,这两者可以是任何引用类型的数据,但key不允许重复。
 key与value之间存在单向的一对一关系。若将Map里的所有key放在一起,它们就组成了一个Set集合,(所有的key没有顺序,key与key之间不能重复)。若将所有value放在一起,它们又类似于一个List,即元素与元素之间可以重复,每个元素可以根据索引来查找,如果需要从Map中取出元素,需要提供该元素的key索引。

1.小结:
Map与Collection的区别:

Map是双列的,Collection是单列的;
Map的键是唯一的,Collection的子体系Set是唯一的;
Map集合的数据结构值针对键有效,跟值无关;Collection集合的数据结构是针对元素有效

2.提供的方法

//添加功能
put(K key,V value)//添加元素
//如果键是第一次储存,就直接储存元素,返回null
//如果不是第一次存在,就用值把以前的值替换掉,返回以前的值

//删除功能
void clear();//移除所有的键值对元素
remove(Obeject key);//根据键删除键值对元素,并把值返回

//判断功能
boolean containsKey(Object key);//判断集合是否包含指定的键
boolean containsValue(Object value)//判断集合是否包含指定的值
boolean isEmpty()//判断集合是否为空

//获取功能
Set <Map.Entry<K,V>> entrySet()
V get(Object key)//根据键获取值
Set<k> keySet()//获取集合中所有键的集合
Collection<V> values()//获取集合中所有值的集合

//长度功能
int size()//返回集合中键值对的个数

3.集合的遍历
法一:迭代器

public static void main(String[] args)
    {
        Map<String, Integer> map =new HashMap<>();
        map.put("张三",23);
        map.put("李四",24);
        map.put("王五",25);
        map.put("赵六",26);

        Integer i=map.get("张三");//根据键获取值
        System.out.println(i);

        //获取所有键
        Set<String> keySet = map.keySet();//获取所有键的集合
        Iterator<String> it=keySet.iterator();//获取迭代器
        while(it.hasNext())//判断集合中是否又元素
        {
            String key=it.next();//获取每个键
            Integer value = map.get(key);//根据键获取值
            System.out.println(key+"="+value);
        }
    }

法二:增强for循环

for(String key : map.keySet())//map.keySet()是所有键的集合
{
	 System.out.println(key+"="+map.get(key));
}

(一).HashMap

HashMap 非线程安全
HashMap:基于哈希表实现。使用HashMap要求添加的键类明确定义了hashCode()和equals()[可以重写hashCode()和equals()].

HashMap:适用于Map中插入、删除和定位元素。

(二).TreeMap

TreeMap:非线程安全基于红黑树实现。TreeMap没有调优选项,因为该树总处于平衡状态。
Treemap:适用于按自然顺序或自定义顺序遍历键(key)。

七.总结:

Collection
 List(存取有序,有索引,可以重复)
  ArrayList:底层是数组实现,线程不安全,查找和修改快,增删比较慢
  LinkedList:底层是链表实现,线程不安全,增删比较快,查找和修改比较慢
  Vector:底层是数组实现,线程安全,无论增删改查都慢

如果查找和修改多,用ArrayList;
如果增和删多,用LinkedList;
如果都多用ArrayList.

 Set(存取无序,无索引,不可以重复)
  HashSet:底层是哈希算法实现
   LinkedHashSet:底层是链表实现的,但也是可以保证元素唯一,和HashSet原理一样
  TreeSet:底层是二叉树算法实现。
Map
 HashMap:底层是哈希算法,针对键
  LinkedHashMap:底层是链表,针对键
 TreeSet:底层是二叉数算法,针对值

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值