java之集合总结

集合概念:

集合和数组都是存储元素用的,二者的区别为:

1.集合

集合是一个容器,它可用来存取对象

集合比数组强大,在一些特定情况下,使用数组不方便,这时就可以使用集合来做

特点:

1.集合长度是可变的

2.可以存储任意类型的object

3.有序也无序

2.数组

数组也是一个容器,可以用来装同一类型的数据

特点:

1.数组定长

2.数据类型相同

3.有下标,可以按顺序遍历

﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋

Collection 体系

集合顶层接口,表示一组对象,有元素唯一和不唯一性,

常用方法有:

1.增加

boolean add(E e) 增加一个对象

boolean addAll(Collection<? extends E> c) 增加一个集合的对象

2.删除

void clear()  移除此Collection中所有的元素

boolean remove(Object o)  删除一个指定的元素

boolean removeAll(Collection<?> c) 删除两个集合中共有的元素(删除交集?)

boolean retainAll(Collection<?> c) 保留两个集合中共有的元素(保留交集)

3.修改

4.查找

boolean contains(Object o)  当前集合中是否包含一个元素

boolean containsAll(Collection<?> c)  判断两个集合中的元素是否完全相同(忽略顺序)

boolean isEmpty()  如果此 collection 不包含元素,则返回 true。 

5.迭代器

对集合中的元素进行遍历。

Iterator<E> iterator()  返回该集合的迭代器

使用迭代器的三个步骤:

1.获取迭代器Iterator<E> it = 集合对象.iterator()

2.通过迭代器判断是否有下一个元素。 it.hasNext()

3.获取集合中的元素it.next()

void remove() 方法和Collection中 boolean remove(Object o) 方法的区别;

最大的区别在于:

在迭代过程中,不能用集合对象对集合进行 remove操作。否则抛出异常。

java.util.ConcurrentModificationException当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。

在使用迭代器中的 remove方法时需要注意

while(it.hasNext()){

it.next();  //要先获取当前元素,再进行操作,否则运行出异常

it.remove();

}

﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋

集合中包含两大类

1.List有序可重复(有序:指存储和取出顺序一致。重复:指满足e1.equals(e2)的元素可重复 )

List中特有方法:

1.查找

E get(int index) 返回列表中指定位置的元素。 

int indexOf(Object o) 返回指定元素在列表中第一次出现的索引

int lastIndexOf(Object o)  返回指定元素在列表中最后一次出现的索引

List<E> subList(int fromIndex, int toIndex) 返回指定索引范围内的元素

2.删除

E remove(int index)  根据指定索引删除指定元素并返回该元素

3.修改

E set(int index, E element)  用指定元素替换掉指定索引上的元素,并返回被替换掉的元素

4.迭代器

ListIterator<E> listIterator()返回该列表的迭代器

ListIterator<E> listIterator(int index)  返回该列表的迭代器,从指定索引开始

ListIterator 列表迭代器。

允许双向遍历列表,迭代器期间可对列表进行操作:增加、删除、替换

注意:倒置遍历的时候,需要正序迭代遍历一次。

List可遍历的方法有三种:

1.父类接口的iterator

2.ListIterator

3.for循环,get(int index) //因为有索引,就可以利用循环操作

1.1.ArrayList *****

底层数据结构是数组,线程不安全[效率高],每次增加元素容量增加 50%查询快、增删慢

1.2.Vector

底层数据结构是数组,线程安全[效率低],每次增加元素容量增加 100%查询快、增删慢

特殊方法(被JDK1.2替代之前的方法)(JDK升级条列中有一条就是:简化书写):

1.增加: void addElement(E obj) -->  boolean add(E e) 

2.删除: E elementAt(int index) -->  E get(int index)

3.迭代器: Enumeration<E> elements() --> iterator(该方法是继承父类的并且没有重写,所以在本类APi中查不到)

1.3.LinkedList

底层数据结构是链表,线程不安全[效率高],查询慢、增删快[提供了头尾元素的操作]

特殊方法:

1.增加

void add(int index, E element) 在指定索引处增加元素

boolean addAll(int index, Collection<? extends E> c) 将指定 collection 中的所有元素从指定位置开始插入此列表。

void addFirst(E e) 将指定元素插入此列表的开头

void addLast(E e)  将指定元素添加到此列表的结尾。

2.删除

E removeFirst() 移除并返回此列表的第一个元素。 

E removeLast() 移除并返回此列表的最后一个元素。 

3.查找

E getFirst() 返回此列表的第一个元素。 

E getLast() 返回此列表的最后一个元素。 

4.迭代器

ListIterator<E> listIterator(int index)  返回以逆向顺序在此双端队列的元素上进行迭代的迭代器。

元素将按从最后一个(尾部)到第一个(头部)的顺序返回。

Iterator<E> descendingIterator()

以后到底使用谁?根据特点判断

线程是否安全?

是:Vector(后期有改进的类替换)

否:用Arraylis 或 LinkedList

是查询多:ArrayList(查询:指遍历,获取等)

是增删多:LinkedList(增:指插入。而头尾操作性能高)

2.Set无序唯一(唯一:不包含满足 e1.equals(e2) 的元素)

1.HashSet

底层数据结构是哈希表,线程不安全[效率高]

1.HashSet 是如何保证元素的唯一?看源码发现:

if (e.hash == hash && ((k = e.key) == key || key.equals(k)))

比较哈希值 &&。。。 || 比较equals

所以HashSet保证元素的唯一性他依赖与两个方法:hashCode 和 equals

重写hashCode:(一般是不需要手动写的)

return this.name.hashCode + this.age * 11(通常写一个素数)

为什么要 * 一个素数?

假设 20 + 30 = 5040 + 10 = 50  ,所以这个样子 返回的哈希值也是相同的,但是对象属性是不同的。就违背了改进的原

让哈希值尽可能的不同,又要尽可能的相同,去比较equals。(看不懂的去看 word笔记)

2.迭代器父类的普通迭代器


2.TreeSet首先无序唯一,但是存储的数据按照自然排序存储。

底层数据结构是二叉树,线程不安全[效率高]元素唯一[性能底,二叉树判断重复、自然排序性能低]

1是如何保证元素的唯一的呢?

有两种实现方式:

1.方式一:让元素本身具备比较性,让自定义类实现Comparable接口

根据返回值进行比较排序

0 :相同

1 :比以前的元素大,放在右边

-1:比以前的元素小,放到左边

返回条件,根据自己的需求比较,返回以上的值

2.方式二:让集合具备比较性。通过构造传递一个Comparator接口的子类对象(暴力强制破坏元素自身的自然比较)

一般可以使用匿名内部类来创建该子类,重写方法的返回值的原理和方式一一样

注意:在开发中,因为TreeSet效率太低,一般使用HashSet

将集合变成数组:

<T> T[] toArray(T[] a)将集合变成数组

a: 存储此 collection 元素的数组(如果其足够大);否则,将为此分配一个具有相同运行时类型的新数组。

Arrays类public static <T> List<T> asList(T... a)将数组变成集合

返回一个受指定数组支持的固定大小的列表。(对返回列表的更改会“直接写”到数组。)


﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋

泛型:Jdk1.5后的新特性

把类型明确的动作放到了创建实例或则调用方法的时候进行【约束我们的类型】

注意:虽然集合可以存储不同类型的对象数据,但是大部分的时候,存储的都是同一种类型数据

使用泛型的好处:

1.将运行期间的问题提前到编译期间解决

2.泛型类优化了程序设计

3.避免了强制类型转换

4.提高了程序的安全性

泛型通配符 ? :

? extends E : 上限:E ?为E的子类即可

? super E: 下限:E  ?为E的父类即可

泛型的使用:泛型可以在类上使用,也可以在接口上使用。

1.自定义泛型类:

泛型位置:在类名后面加上typeOf   <T> //T为变量,一般t表示为数据类型

在类上声明的泛型可以在类的【实例】成员上使用.

类的成员:

1.成员属性:实例属性(非static)类属性(static)

2.成员方法:实例方法类方法

为什么只能在类的实列成员上使用:

因为静态成员随着类的加载而加载,不需要对象就可以使用,这时泛型就没有初始化。

2.自定义泛型方法:

泛型位置:声明在修饰符与方法返回类型之间。

泛型方法的作用:

不想使用类上声明的泛型,想要在参数和返回值之间建立起关联,就可以在方法上声明泛型

类泛型不能用在static方法上,但是可以在方法上自定义泛型

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值