一、概述 集合框架是Java一块很重要的内容,对常用的数据结构做了规范和实现。对象封装了数据,许多对象则构成了所谓集合。Java集合类库构成了集合类的框架。它为集合的实现者定义了大量的接口和抽象类,并且对其中的某些机制给予了描述。 集合框架的接口和实现类: 二、Iterator接口 Iterator接口与Collection系列、Map系列的集合不一样:Collection系列集合、Map系列集合主要用于盛装其他对象,而Iterator则主要用于遍历(即迭代访问)Collection集合中的元素,Iterator对象也被称为迭代器。[引 ] Iterator接口定义了四个方法 –boolean hasNext():如果被迭代的集合还元素没有被遍历,则返回true。 –Object next():返回集合里下一个元素。 –void remove() :删除集合里上一次next方法返回的元素 –void forEachRemaining(Consumer action):这是Java 8为Iterator新增的默认方法,该方法可使用Lambda表达式来遍历集合元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 /** * @author shen * @desc Iterator接口 * @date 2016年8月23日 */ public class IteratorTest { public static void main(String[] args) { //Iterator是Collection父接口,可如此创建集合 Collection<Object> animals = new HashSet<>(); //添加元素 animals.add("cat"); animals.add("dog"); animals.add("pig"); //使用Lambda表达式遍历集合(java1.8新特性) animals.forEach(obj -> System.out.println("Lambda迭代输出:" + obj)); //iterator()方法获取迭代器 Iterator<Object> data = animals.iterator(); while(data.hasNext()){ Object subData = data.next(); if("cat".equals(subData)){ data.remove();//移除元素 } System.out.println("迭代器输出:" + subData); } System.out.println(animals); } }
输出:
三、Collection接口 Collection不提供接口的任何直接实现,一个Collection代表一组Object,但它提供更加具体的子接口如List和Set,而继承自它们的 ArrayList, Vector, HashTable, HashMap等实现类才可被实例化。 1、List接口 List是一个有序集合(ordered collection)。元素可以添加到容器中某个特定的位置。将对象放置在某个位置上可以采用两种方式:使用整数索引或使用列表迭代器。[引 java核心技术] List接口实现类主要有:ArrayList、Vector、LinkedList。 (1)ArrayList ArrayList是List接口的可变数组的实现,其操作基本是对数组的操作,ArrayList是线程不安全的。 ArrayList包装了许多的方法,包括元素的增加移除、插入移动、转换数组等等:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 /** * @author shen * @desc * @date 2016年8月23日 */ public class ListTest { public static void main(String[] args) { List<String> list = new ArrayList<String>(); list.add("1");//使用list时默认长度置为10 list.add("2"); list.add("3"); list.add("4"); list.add("5"); System.out.println("list输出:"+list); list.remove(4);//移除元素 System.out.println("移除元素之后的list:"+list); Object[] arr = list.toArray();//转换为数组 System.out.println("数组元素输出:"+arr[0]); List<String> c = new ArrayList<>(4);//预计有4个元素而创建 c.add("6"); c.add("7"); c.add("8"); c.add("9"); c.add("10");//超过5个元素list会增加原来长度一半个元素,目前即长度为6 list.addAll(c);//增加一组数据,数据类型应相同 System.out.println(list); Iterator<String> data = list.iterator();//获取迭代器 System.out.println("迭代输出:"); data.forEachRemaining(action -> System.out.print(action+" ")); } }
输出: ArrayList的各种操作虽然很方便,但是ArrayList的插入和删除,会导致内部数据大量移位,而扩容则需要新建一个ArrayList将原来的数据复制过去,会影响性能。如果我们已经知道需要的元素个数,我们可以初始化时指定ArrayList的容量,这样可以有效的避免数组多次扩充,从而提高效率。 (2)Vector Vector类提供了实现可增长数组的功能,随着更多元素加入其中,数组变的更大。在删除一些元素之后,数组变小,而不像ArrayList的扩容方式,基本用法与ArrayList相同。Vector是同步类,是线程安全的。 (3)LinkedList LinkedList是list的链表实现,列表中的每个节点都包含了对前一个和后一个元素的引用,除了大部分与ArrayList相同的方法,LinkedList还有一些其特有的方法,并且LinkedList在添加和删除元素时具有比ArrayList更好的性能,但在get数据时更慢。LinkedList适用于没有大规模的随机读取,大量的增加/删除操作。[引 ]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class LinkTest { public static void main(String[] args) { LinkedList<String> link = new LinkedList<>(); link.add("a"); link.add("b"); link.add("c"); link.add("d"); link.add("e"); System.out.println("第一个元素:"+link.getFirst()+" 最后一个元素:"+link.getLast()); link.remove(1); System.out.println(link); link.add(3, "zhiding"); System.out.println(link); } }
输出:
2、Set接口 由于Set接口提供的数据结构是数学意义上集合概念的抽象,因此它需要支持对象的添加、删除,而不需提供随机访问。Set具有与Collection完全一样的接口,因此没有任何额外的功能。实际上Set就是Collection,只是行为不同。Set不包含重复的元素。 Set的实现类主要有:HashSet,TreeSet,LinkedHashSet (1)HashSet 不保证set的迭代顺序,不保证该顺序永恒不变,因此HashSet也没有get方法。此类允许使用null元素,底层是使用HashMap实现的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public static void main(String[] args) { HashSet<String> set = new HashSet<>(); set.add("adf"); set.add("bhf"); set.add("c32"); set.add("c32");//有重复元素,添加不了 set.add(null);//null也只允许只有一个 System.out.println(set); for(String str : set){ System.out.print(str +" "); } System.out.println(); Iterator<String> iterator = set.iterator(); while(iterator.hasNext()){ String data = iterator.next(); System.out.print(data +" "); } } 输出: [null, bhf, adf, c32] null bhf adf c32 null bhf adf c32
(2)TreeSet TreeSet元素自然排序,底层是使用TreeMap实现的,自定义要显示Comparable接口。TreeSet可以给集合中的元素进行指定方式的排序,保证元素唯一性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 /** * @author shen * @desc 测试类,实现Comparable<T>接口 * @date 2016年8月24日 */ public class User implements Comparable<User>{ private String name; private int age; //构造 public User(String name,int age){ this.name = name; this.age = age; } //实现类 @Override public int compareTo(User user) { if(user == null) throw new NullPointerException(); if(this.age > user.age) return 1; if(this.age < user.age) return -1; return 0; } //重写toString @Override public String toString() { return "User [name=" + name + ", age=" + age + "]"; } } //测试 public static void main(String[] args) { Set<User> set = new TreeSet<User>(); User user1 = new User("Tom", 20); User user2 = new User("Jack", 21); User user3 = new User("Dave", 22); User user4 = new User("Jane", 12); set.add(user1); set.add(user1);//重复,添加不了 set.add(user2); set.add(user3); set.add(user4); System.out.println("按年龄大小输出:"); System.out.println(set); } 输出 按年龄大小输出: [User [name=Jane, age=12], User [name=Tom, age=20], User [name=Jack, age=21], User [name=Dave, age=22]]
(3)LinkedHashSet LinkedHashSet集合同样是根据元素的hashCode值来决定元素的存储位置,但是它同时使用链表维护元素的次序。这样使得元素看起 来像是以插入顺序保存的,也就是说,当遍历该集合时候,LinkedHashSet将会以元素的添加顺序访问集合的元素。 LinkedHashSet在迭代访问Set中的全部元素时,性能比HashSet好,但是插入时性能稍微逊色于HashSet。[引 ]
四、Map接口 在Collection实现中保存的直接是一个个对象,二在Map实现中保存的是一对对象,以键值对key-value的方式关联着。Map的常用实现类有HashMap,HashTabel和TreeMap。 1、HashMap HashMap是基于哈希表的Map接口的非同步实现,其中元素表现无序,特别是它不保证该顺序恒久不变。HashMap会利用对象的hashCode来快速找到key。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 public static void main(String[] args) { //使用实现类创建,键值指定对象类型 HashMap<String, String> map = new HashMap<>(); map.put("name", "shen"); map.put("age", "20"); map.put("age", "19");//相同键多次存入数据覆盖 map.put("weight", "100"); map.put(null, "空");//允许空键值 map.put(null, null); System.out.println(map); //对map集合的遍历,可取出具体的键和对应值 for(Entry<String, String> element:map.entrySet()){ String key = element.getKey(); String value = element.getValue(); Class<? extends Entry> classData = element.getClass(); System.out.println(key + "---- " + value + "---- " + classData.getName()); } //使用接口创建,不关心具体实现,只有在使用才具体实现 //键值的值一般设为Object,不关心什么类型的数据,当然,获取需要具体数据类型或对象需要转化 Map<String, Object> mapData = null;//new HashMap<>(); mapData = new HashMap<>(); mapData.put("name", "Jack"); mapData.put("age", 21); mapData.put("weight", 110.5); System.out.println(mapData); System.out.println("获取name值:" + mapData.get("name")); Set<String> keys = mapData.keySet(); System.out.println("获取所有key:" + keys); Collection<Object> values = mapData.values(); System.out.println("获取所有value:" + values); } 输出: {null=null, name=shen, weight=100, age=19} null---- null---- java.util.HashMap$Node name---- shen---- java.util.HashMap$Node weight---- 100---- java.util.HashMap$Node age---- 19---- java.util.HashMap$Node {name=Jack, weight=110.5, age=21} 获取name值:Jack 获取所有key:[name, weight, age] 获取所有value:[Jack, 110.5, 21]
2、HashTabel HashTable在很大程度事实上和HashMap的实现差不多,主要区别是HashMap采用异步处理方式,性能更高,而HashTabel采用同步处理方式,性能较低。HashTabel属于线程安全类而HashMap属于线程不安全类。[参考 ]
3、TreeMap TreeMap是可排序的Map集合按照集合中的key进行排序,key不允许重复。TreeMap是红黑树基于Map接口的实现。关于TreeMap红黑树参考 ,初次接触不容易理解,多查资料。