java集合

Collection集合常用方法

boolean add(E e);      //向集合中添加元素
boolean remove(E e);   //删除集合中的某个元素
void clear();          //清空集合中所有元素
boolean contains(E e); //判断集合中是否包含某个元素
boolean isEmpty();     //判断集合是否为空
int size();            //获取集合的长度
Object[] toArray();    //将集合转换成一个数组

迭代器

Collection集合元素的通用获取方式。在取元素前要判断集合中有没有元素。

使用集合中的方法iterator()获取迭代器的实现类对象

Iterator 接口包含4个方法

public interface Iterator<E> {
    E next();
    boolean hasNext();
    void remove();
    default void forEachRemaining(Consumer<? super E> action);
}

应该将Java迭代器认为是位于两个元素之间,调用next时,迭代器就越过下一个元素,并返回刚刚越过的那个元素的引用。但是到达集合末尾,next方法会抛出NosuchElementException。因此,需要在调用next方法前调用hasNext方法,返回true时调用next方法。remove方法会删除上次调用next方法时返回的元素,例如若要删除两个相邻元素,必须先调用next方法。

iterator.remove();
iterator.next();
iterator.remove();

List接口

特点:

  • 有序的集合
  • 允许存储相同的元素
  • 有索引,可以使用for循环遍历

ArrayList

特点:底层是数组实现的,查询快,增删慢。

LinkedList

特点:底层是链表实现的,查询慢,增删快。

在Java程序设计语言中,所有的链表实际上都是双向链接的。

数组和数组列表都有一个重大的缺陷:想要从中间位置删除一个元素要付出很大的代价,其原因是删除中间元素后,其后的所有元素都要向前端移动。插入一个元素也是如此。

链表解决了这个问题

元素删除与上述一致,这里需要说明的是,为了实现在任意位置添加元素,集合类库提供了子接口ListIterator,其中包含了add方法,与Collection.add不同,这个方法不返回boolean类型的值,它假定添加操作总会改变链表。add方法会在迭代器位置之前添加一个新对象。

另外,ListIterator接口有两个方法,可以用来反向遍历链表:

E previous();
boolean hasPrevious();

与next方法一样,previous方法返回越过的对象。

通过一下代码示例来说明:

LinkedList<String> staff = new LinkedList<>();
staff.add("Amy");
staff.add("Bob");
staff.add("Carl");
ListIterator<String> iterator = staff.listIterator();
iterator.next();
iterator.add("Juliet");
iterator.previous();
iterator.remove();

最后的remove方法将刚刚添加进去的“Juliet”删除了,同样是删除previous越过的元素。

简而言之:add方法只依赖于迭代器的位置,而remove方法依赖于迭代器的状态

最后还有set方法,用一个新的元素取代调用next或previous方法返回的上一个元素。

多个迭代器的使用

如果迭代器发现它的集合被另一个迭代器修改了,或是被该集合自身的方法修改了,救会抛出一个ConcurrentModificationException异常。例如:

List<String> list = ...;
ListIterator<String> iter1 = list.listIterator();
ListIterator<String> iter2 = list.listIterator();
iter1.next();
iter1.remove();
iter2.next();// throws ConcurrentModificationException

为了避免并发修改的异常,可以遵循下述规则:可以给容器附加许多的迭代器,但这些只能读取列表。再单独附加一个既能读又能写的迭代器

常用方法:

void addFirst(E e);      //将指定元素插入到链表的头部
void addLast(E e);       //将指定元素插入到链表的尾部
void getFirst();
void getLast();
E removeFirst();
E removeLast();          //移除并返回

链表也有get方法根据索引来获取元素,但效率很低,如果要随机访问,就不应该使用链表。

Set接口

特点:

  • 不允许存储重复的元素
  • 没用索引(不能使用普通的for循环遍历)

HashSet

特点:底层是哈希表+(红黑树)实现的,无索引,不可以存储重复元素,存取无序。

构造函数:

HashSet();          //构造一个空散列表,默认容量16,装填因子0.75
HashSet(Collection<? extends E> elements);    //构造一个散列集,将集合中的元素加到其中
HashSet(int initialCapacity);             //构造一个空的具有指定容量的散列集
HashSet(int initialCapacity, float loadFactor);  //装填因子(0.0-1.0)
Capacity

如果想要控制散列表的运行性能,就要指定一个初始的桶数(容量)。桶数是指用于收集具有相同散列值的桶的数目。(散列值与桶的总数取余,所得到的结果就是保存这个元素桶的索引,例如,某个对象的散列值为76268,并且有128个桶,对象就保存在76268%128 = 108号桶中)。通常将桶数设置为预计元素个数的75%-150%。参数initialCapacity是2的幂,默认16,例如,及时设置为5,也会被改成8

load factor

如果散列表太满,就需要再散列(rehashed):创建一个桶数更多的表,并将所有元素插入到这个新表中,然后丢弃原来的表。装填因子(load factor)决定何时进行再散列,例如,为0.75(默认值),那么表中超过75%的位置已经填入元素,这个表就会用双倍的桶数进行再散列。

hashCode

如果自定义类,就要负责实现这个类的hashCode方法,自己实现的hashCode方法应该与equals方法兼容,即如果a.equals(b)为true,则a,b必须具有相同的散列码。


LinkedHashSet

特点:底层是哈希表+链表实现的,无索引、不可以存储重复元素、可以保证存取顺序

TreeSet

特点:底层是二叉树实现,一般用于排序

注意:由于每次插入元素时,都会被放在正确的排序位置上,放入树集的元素必须实现Comparable接口,或者构造集时必须提供一个Comparator

Queue&Deque接口

特点:

  • 可以在尾部添加一个元素,在头部删除一个元素
  • 不支持在队列中间添加元素
  • 双端队列可以在头部尾部同时添加或删除元素

常用方法:

java.util.Queue<E>
boolean offer(E element);                 //将元素添加到尾端,如果队列满了,返回false
E poll();                                 //删除并返回队列头部的元素,队列为空则返回null
E peak();                                 //返回队列头部元素(不删除),为空则返回null
//与上述三个方法类似的有add(),remove()和element方法,但失败都会抛出异常


java.util.Deque<E>
boolean offerFirst(E element);            //添加到头部
boolean offerLast(E element);             //添加到尾部
E pollFirst();           
E pollLast(); 
E peakFirst();  
E peakLast();

PriorityQueue

特点:

  • 按任意顺序插入,按特定顺序检索(无论何时调用remove方法,都会获得队列中最小的元素)
  • 堆数据结构
  • 元素要实现Comparable接口,或者构造时必须提供一个Comparator

Map集合

特点:

  • 存放键/值对,通过唯一的键查找值

常用方法:

V get(Object key);               //返回与键对应的对象,如果没有则返回null
default V getOrDefault(Object key,V defaultValue);      //如果没有则返回这个默认值
V put(K key, V value);          //存放键值对,如果键已经存在则覆盖值,返回原有的值
void putAll(Map<? extends K, ? extends V> entries);    //放入给定映射中的所有条目
boolean containsKey(Object key);
boolean containsValue(Object value);
default void forEach(BiConsumer<? super K,? super V> action);
//对所有键值对执行这个动作,可以使用lamda表达式

HashMap

特点:

  • 允许存入null键,null值(null值只有一个,并存于数组第一个位置)
  • 无序集合,而且顺序会随着元素的添加而随时改变(添加顺序,迭代顺序不一致)
  • 随着元素的增加而动态扩容(与ArrayList原理一致)
  • 不存在重复元素(得益于hashCode算法和equals方法)
  • 线程不安全

TreeMap

特点:

  • 不允许出现重复的key
  • 可以插入null键,null值
  • 可以对元素进行排序
  • 无序集合(插入和遍历顺序不一致)

未完待续…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值