1.java集合分为set(无序不可重复)、list(有序可重复)、map(映射)、queue(队列集合)。可以把它们看作一种容器,装载着对象的引用。集合和数组的区别在于数组一旦大小确定就不能继续变了,并且集合只能保存对象的引用,数组除了对象引用还可以保存基本类型。集合都放在java.util下,在java5后针对多线程又添加了一个包java.util.concurrent。所有集合都是继承collection和map两个接口。
常用的实现类有hashset,treeset,arraylist,linkedlist,arraydeque,hashmap(线程不安全),hashtable(线程安全),treemap。对于线程安全的集合放在后面多线程时候学习。
2.collection提供了一些操作方法,其中需要记住的是:toarray()方法把集合转换成数组,iterator()方法返回一个集合遍历对象,其他无非对集合的增删改查判断。并且实现collection的子类都重写了tostring()方法。
3.遍历集合可以使用foreach方法的lambda表达式,因为collection是继承至iterable,而iterable中有foreach方法,因此collection集合都有此方法。如:books.forEach(obj->system.out.printin(obj));还有一种方法是iterator迭代器,通过集合获取该迭代器后可以逐个访问集合元素。通过iterator可以删除集合中元素,但是不能通过集合本身修改集合(添加元素,删除元素)。iterator也提供了lambda表达式遍历。最简单的是使用foreach(元素:集合)方式循环访问,切记不要修改集合本身。集合提供了谓词来对集合有条件批量删除,如:c.removeIf(Predicate a),传递一个lambda表达式后根据条件删除。谓词功能非常有用,相当于对函数进行抽象,在不同的地方使用lambda表达式传递一个谓词给函数执行相应的操作。所有集合可以使用java8提供的stream流式API来操作,这样结合谓词更简单(主要处理集合的聚集操作)。
4.set中常用的是hashset(操作快使用hash算法),之后是linkedhashset(使用也是hash算法放,但是以链表记录,读取是按照加入时顺序),treeset(一个根据某个规则排序的set,使用的是红黑树算法。比一般的set多了几个方法,第一个,最后一个,某元素的前一个,某元素的后一个,以及3个获取顺序中某段treeset)。向treeset中添加的对象必须实现了comparable接口,这样才能比较后排序,如果不用默认的排序方法可以自定义排序函数在创建treeset时候传给它,treeset中的元素必须是同一个类型,不同类型的comparable比较不一样会产生异常。由于set的存储位置根据元素的某些字段计算得出,因此不管是hashset还是treeset中一旦添加了元素,最好不要在修改这些元素的值。总结:常用的是hashset读取和查找都快,如果需要排序用treeset(用了红黑树比较慢),linkedhashset在删除和插入时候稍微慢,但是由于维护了链表在读取速度快于hashset。Enumset是最快的但是只用于同一种枚举上。以上所有集合都是线程不安全的,一般在Collections.synchronizedXX下包装。
5.list集合根据加入顺序自动生成有序集合并且允许元素重复,list新加了sort(提供comparable方法)方法重新排序和replaceAll(operator是一个函数带一个参数,并且返回一个值)重新设置集合里的所有元素。list在进行操作的时候是对元素的equel方法进行对比,如果相同则开始执行。list有个方法返回一个ListIterator,它继承Iterator,并且提供了向前迭代和添加元素(Iterator只能向后迭代只能删除元素)。arraylist和vector是list的2个实现,他们都用了数组来实现,在集合内部维护了一个集合的容量变量,该变量会自动根据容器大小自动变化。还有一个常用是LinkedList,它是用链表的方式实现的,读操作arraylist快,删除和添加linkedlist快(只需要维护一下链表),list的实现类都可以随机访问。
6.集合与数组之间的转换:arrayList.toArray()转换为数组(使用集合对象自带方法转换),Arrays.asList(dd),转化后得到的集合是arrays工具类下的定义的内部类,与平常使用的arraylist不一样,它只能遍历不能删除和修改。
7.queue提供顺序访问不能随机访问,有priorityqueue(单向队列先进先出,但实际它并不是先进先出,它进行了排序,所以用的并不多)和deque(双端队列接口,同样就实现了栈的功能。实现有arraydeque和linkedList),提供了一些添加获取方法。arraydeque和arraylist一样底层都是用一个可变数组进行维护。对于linkedlist它实现了2个接口(list和deque),因此既有队列的概念又有列表的概念,这样的数据结构有个好处就是,如果当做栈使用时只能是先进后出,但是某些已经入栈的数据由于某种原因需要特殊处理,可以把它当做列表随机访问后做修改或者删除等操作。linkedlist是一个强大的数据结构。
8.对于list,arraylist应该使用get下标方式访问(数组下标访问快),linkedlist使用iterator(链表只有一个个来)。如果经常有大量的删除新增等操作应该使用linkedlist(只是改变节点的指向)。
9.map接口实现类有hashmap,linkedhashmap,hashtable(线程安全,一种古老的类,尽量少用即使在多线程情况也应该用collections包装hashmap使用),properties(非常方便的解决了属性文件直接映射到map中,同样也方便属性对象直接持久化到文件,分别使用load和store),enummap(key只能是某个枚举的值,value可以任意,操作很快),sortedmap,treemap等。除了提供一些简单的操作外java8还增加了一些额外的待函数的方法操作。和hashset类似尽量使用不可变对象作为key,如果非要使用变化的变量作为key那么千万不要取修改key的值。和linkedhashset类似linkedhashmap在数据加入时也维护了一个双向链表,在插入时性能低于hashmap但是在全部数据遍历时linkedhashmap性能好于hashmap。
10.hash存储发是通过hash计算出元素需要存储的位置,每个存储元素的单位叫桶,正常情况下一个桶存储一个元素,但是由于hash桶是开放的如果hash出现冲突则会在一个桶中存储多个元素,元素之间用链表的形式保存。hashtable,hashmap,hashset以及其子类在初始化时候会自动设置一个容量大小,默认元素存储数量超过75%会自动重新分配一个原来桶大小2倍的容器。
11.在集合中java提供了collections工具对集合进行排序、查找、替换、多线程包装、设置不可变集合等。