您现在的位置是:首页 > 文章详情

Java学习----Collection总结

日期:2018-10-31点击:372

Java----Collection总结

集合,存储多个元素的容器----大小不定。
在集合这块主要的内容有:
接口:Collection Iterator List   Set  Map
类:ArrayList   LinkedList  stack queue
hashMap  hashTable


本篇为Collection的总结,才开始学习Java,在集合这块看资料总是感觉一团乱麻。所以写这个总结,一方面把自己知道的东西梳理一下,另一方面初学水平有限,如果有错误还请各位大神能够指点,还有就是刚开始玩社区,希望能够获取一点积分,嘿嘿。希望有一天,能够学习JAVA,加入Ali。

Collection接口

Collection是集合层次的根接口。由于泛型的限制,集合中只能存储对象。泛型只能表示引用类型。
Collection定义中的主要方法,就是说当要实现一个Collection的时候,要先实现以下方法(不全,可以查看API稳定):


public interface Collection<E> extends Iterable<E>{ int size(); boolean isEmpty(); void clear(); boolean contains(); boolean add(); boolean remove(); Iterator<E> iterator(); }


实现一个Collection,在ArrayList中实现了List接口,而List接口继承了Collection接口,所以可以用下面方式来实现一个Collection集合,然后可以用上述方法。
Collection<String> c = new ArrayList<String>();


List接口

List接口是Collection的子接口,用于定义线性表数据结构。可以将List理解为存放对象的动态数组,只不过其元素个数可以动态的增加或者减少。List接口两个常见的实现类是ArrayList和LinkedList。分别用动态数组和链表的方式实现了List接口。(这两种实现方式在文末附上)

public interface List<E> extends Collection<E> { Anytype get(int idx); Anytype set(int idx, Anytype newVal); void add(int idx, Anytype x); void remove(int idx); Iterator<Integer> listIterator(int pos); } 


重要方法:

List<E> list = new ArrayList<>(); E get(int idx) 获取集合中指定下标对应的元素 E set(int idx,E element) 给定下标上的元素,并将原来的元素返回 E add(int idx,E element) 在给定下标出添加元素,原位置及以后的元素都后移 E remove(int idx) 删除给定位置的元素,并将被删除的元素返回 List<E> sublist(int formIdx,int toIdx)获得List中的子序列(前包括,后不包括) Object[] toArray() <T> [] t = toArray(T[] a) String [] strArr = list.toArray(new String []()); 将List转成数组,第二种比较常用 static List<T> list = asList<T[]a> String [] strArr = {"a","b","c"}; List<String> list = Arrays.asList(strArr);将数组转换成list。

Iterator接口

public interface Iterator<E> { boolean hasNext(); Anytype next(); void remove(); }

迭代器用于遍历集合元素。获取迭代器,可以使用Collection中的方法,Iterator iterator()。具体用法如下代码。:

Set<String> set = new HashSet<String>(); set.add("a"); set.add("b"); //建立一个指向set的迭代器 Iterator<String> it = set.iterator(); while(it.hasNext()){ String str = it.next(); System.out.println(str); //删除元素 it.remove(); } System.out.println(set);
注意:迭代器在遍历元素时,不能通过集合的remove方法来删除元素,否则会抛出异常。但是可以通过迭代器自身提供的方法的remove方法来删除,具体实现方式在LinkedList的实现代码中有。 


Collections 操作集


Collections操作集是为collection及其子接口、类提供操作方法的一个操作集。(几乎用不到)但是有sort()方法比较重要。
void sort(List<T> list);
直接使用该方法是自然排序,也可以使用Comparable 和Comparator。
Collection中的sort()能够排序的主要原因是,传入的集合元素都是Comparable接口的实现类,该接口表示子类是可以比较的,因为实现该接口重写抽象方法 int compareTo(T t);
该方法用于当前对象与给定对象进行比较:
 若当前对象大于给定对象,则返回值应为大于0的整数
 若当前对象小于给定对象,则返回值应为小于0的整数
 若两个对象相等,则返回值等于0
一旦java类实现了comparable接口,其比较规则就已经确定。如果想要在排序中临时指定规则,可以采用Comparator接口回调的方式,具体使用如下:

list.sort(new Comparator<String>(){ //比较规则写在这 //如果返回值>0,那么就会将o2排在o1之前 //如果返回值<0,那么就会将o1排在o2之前 public int compare(String o1,String o2){ //return o1.compareTo(o2); return o1.charAt(0) - o2.charAt(0); } }); 

Set接口--散列集合

不包含重复元素的集合(唯一)
Set的具体用法跟list差不多,这里代码不再重复写。
Set<String> set = new HashSet<String>();
HashSet
底层基于hashMap来进行存储,不保证迭代顺序,并且不保证循序不变。
HashMap
是基于数组+链表来进行存储。底层数组初始容量为16.数组中的每一个位置称之为是一个桶-bucket
O1---先计算o1的hash码--哈希码是int类型的整数--针对哈希码进行二次运算,使运算结果落在桶的编号之中。
每一个桶中维系了一个链表。添加新元素时,先比较与桶中的元素是否相等,不相等,加入到链表,有相等就舍弃。放的越晚的元素,比较就越低,增删改效率都会降低。所以想要缩短链的长度,就得增加桶的个数。扩容,每次都是一倍。
如果已经使用的桶的数量/桶的总数量>加载因子,那么就认为需要扩容。默认加载因子是0.75。扩容之后,会对桶中的元素进行重新的计算和分布,是元素散列在新找的桶中--rehash。
Rehash---元素越多,效率越低。当你进行rehash的时候,是不能往里面放元素的。
加载因子:影响扩容,越小会扩容越频繁。同时会导致内存的浪费。效率变低。加载因子越大,会导致每一个桶汇中的链表会变长而导致查找变慢。
public HashSet(int initialCapacity),允许指定初始容量和加载因子。
总的效率,一开始是高的,然后慢慢变慢。在JDK1.8中,如果链的长度>8,那么会将这个链扭转成红黑树,自平衡二叉树。红黑树,比节点小,往左放,比节点大,往右放,类似二分查找。如果红黑红树的节点个数<=6,会扭回链表。

Map接口

一组自变量按照某种规则变成另外一组因变量,就叫做映射。
K -key-键,V-value-值。一个键对应一个值 - 键值对。也就意味着,一个映射实际上是由多个键值对组成。在映射中,键是唯一的。一个键最多只能对应一个值。
实现类HashMap与HashTab

HashMap<K,V>

底层是基于数组+链表的结构。允许键或者值为null。默认初始容量是16,加载因子是0.75.。这个类不保证数据的顺序map是计算key的哈希码,可以针对哈希码来进行二次运算,决定存到哪个桶中。尤其是不保证这个顺序恒久不变。默认rehash扩容,每次会增加大约两倍空间。如果是一个比较高的加载因子,
hashMap允许指定初始容量。指定的初始容量在[2^x , 2^x+1]之间,那么容量算出来的一定是为2^x+1。指定这么大是为了扩容的时候,直接左移一位。本身是一个异步式线程不安全的映射。
异步式:如果一个对象在同一个时刻内允许多人操作
同步式:如果一个对象在一个时刻内允许一个人操作

Map<String, Integer> map = new HashMap<>(); map.put("d",6); map.put("e",4); map.put("s",3); map.put("f",9); map.put("i",4); //如果键值相同,对应的值覆盖 map.put("i", 3); //判断是否包含这个键 System.out.println(map.containsKey("a")); System.out.println(map.containsValue(7)); //移除键值对 map.remove("i"); //如果键相同,那么对应的值覆盖 //清空映射 map.clear(); //获取指定的键所对应的值 System.out.println(map.get("r")); //将映射中所有的值放入一个集合返回 Collection<Integer> c = map.values(); System.out.println(c);

HashTbale

不允许键或者值为null.底层也是基于数组+链表。底层的默认初始容量是11.加载因子为0.75F,默认扩容增加一倍,然后再+1。(官方没有解释为什么这样)
这个映射本身是一个同步式线程安全的映射。
指定初始容量,指定多少,就是多少。
基本上没有用,效率比较低,只会出现在面试的时候。

List接口 自己写的LinkedList的实现


package ADT; import java.security.NoSuchAlgorithmException; import java.util.ConcurrentModificationException; import java.util.Iterator; import java.util.NoSuchElementException; import java.lang.String; public class myLinkedList<String> implements Iterable<String> { private static class Node<String> { public Node(String d, Node<String> p, Node<String> n) { data = d; prev = p; next = n; } public String data; public Node<String> prev; public Node<String> next; } public myLinkedList() { doclear(); } public void clear() { doclear(); } public void doclear() { beginMarker = new Node<String>(null, null, null); endMarker = new Node<String>(null, beginMarker, null); beginMarker.next = endMarker; theSize = 0; modCount++; } public int size() { return theSize; } public boolean isEmpty() { return size() == 0; } public boolean add(String x) { add(size(), x); return true; } public void add(int idx, String x) { addBefore(getNode(idx, 0, size()), x); } public String get(int idx) { return getNode(idx).data; } public String set(int idx, String val) { Node<String> p = getNode(idx); String oldval = p.data; p.data = val; return oldval; } public String remove(int idx) { return remove(getNode(idx)); } private void addBefore(Node<String> p, String x) { Node<String> newnode = new Node<>(x, p.prev, p); newnode.prev.next = newnode; p.prev = newnode; theSize++; modCount++; } private String remove(Node<String> p) { p.prev.next = p.next; p.next.prev = p.prev; theSize--; modCount++; return p.data; } private Node<String> getNode(int idx) { return getNode(idx, 0, size() - 1); } private Node<String> getNode(int idx, int low, int up) { Node<String> p; if (idx < low || idx > up) { throw new IndexOutOfBoundsException(); } if (idx < size() / 2) { p = beginMarker; for (int i = 0; i < idx; i++) p = p.next; } else { p = endMarker; for (int i = size(); i > idx; i--) p = p.prev; } return p; } @Override public Iterator<String> iterator() { // TODO Auto-generated method stub return new LinkedIterator(); } private class LinkedIterator implements Iterator<String> { private Node<String> current = beginMarker.next; private int exceptedModecount = modCount; private boolean okToRemove = false; @Override public boolean hasNext() { // TODO Auto-generated method stub return current != endMarker; } @Override public String next() { // TODO Auto-generated method stub if (modCount != exceptedModecount) throw new ConcurrentModificationException(); if (!hasNext()) throw new NoSuchElementException(); String nextItem = current.data; current = current.next; okToRemove = true; return nextItem; } public void remove() { if (modCount != exceptedModecount) throw new ConcurrentModificationException(); if (!okToRemove) throw new IllegalStateException(); myLinkedList.this.remove(current.prev); exceptedModecount++; okToRemove = false; } } @Override public java.lang.String toString() { StringBuilder sb = new StringBuilder("["); Node node = this.beginMarker; while (node != null) { sb.append(node.data).append(", "); node = node.next; } java.lang.String str = sb.toString(); if (size() != 0) str = str.substring(0, str.length() - 2); return str += "]"; } private Node<String> beginMarker; private Node<String> endMarker; private int theSize; private int modCount = 0; }


原文链接:https://yq.aliyun.com/articles/662659
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章