一、Collection接口方法:Collection 接口是 List、Set 和 Queue 接口的父接口,该接口里定义的方法既可用于操作 Set 集合,也可用于操作 List 和 Queue 集合。JDK不提供此接口的任何直接实现,而是提供更具体的子接口(如:Set和List)实现。
1、添加
- add(Object obj)
- addAll(Collection coll):将coll中的元素添加到当前集合中
2、获取有效元素的个数
- int size()
3、清空集合
- void clear()
4、是否是空集合
- boolean isEmpty()
5、是否包含某个元素
- boolean contains(Object obj):判断是否包含obj,是通过元素的equals方法来判断是否是同一个对象
- boolean containsAll(Collection c):也是调用元素的equals方法来比
较的。拿两个集合的元素挨个比较。
6、删除
- boolean remove(Object obj) :通过元素的equals方法判断是否是要删除的那个元素。只会删除找到的第一个元素
- boolean removeAll(Collection coll):取当前集合的差集
7、取两个集合的交集
- boolean retainAll(Collection c):把交集的结果存在当前集合中,不影响c
8、集合是否相等
- boolean equals(Object obj)
9、转成对象数组
- Object[] toArray()
10、获取集合对象的哈希值
- hashCode()
11、遍历
- iterator():返回迭代器对象,用于集合遍历
二、Iterator迭代器接口:
- Iterator对象称为迭代器(设计模式的一种),主要用于遍历 Collection 集合中的元素。迭代器模式,就是为容器而生;
- Collection接口继承了java.lang.Iterable接口,该接口有一个iterator()方法,那么所有实现了Collection接口的集合类都有一个iterator()方法,用以返回一个实现了Iterator接口的对象;
- Iterator 仅用于遍历集合,Iterator 本身并不提供承装对象的能力,如果需要创建Iterator 对象,则必须有一个被迭代的集合;
- 集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前。
1 @Test //迭代器中的remove() 2 public void test2(){ 3 Collection collection1 = new ArrayList(); 4 collection1.add("A"); 5 collection1.add("B"); 6 collection1.add("Jerry"); 7 8 //移除操作 9 Iterator iterator = collection1.iterator(); 10 while(iterator.hasNext()){ 11 Object next = iterator.next(); 12 if("B".equals(next)) 13 iterator.remove(); 14 15 } 16 17 //从头开始遍历 18 iterator = collection1.iterator();//必须重新生成,不然接上面的集合最后 19 while(iterator.hasNext()){ 20 System.out.println(iterator.next()); 21 } 22 }
注意:
- Iterator可以删除集合的元素,但是是遍历过程中通过迭代器对象的remove方法,不是集合对象的remove方法。
- 如果还未调用next()或在上一次调用 next 方法之后已经调用了 remove 方法,再调用remove都会报IllegalStateException。
三、Collection子接口——List:List集合类中元素有序、且可重复,集合中的每个元素都有其对应的顺序索引。JDK API中List接口的实现类常用的有:ArrayList、LinkedList和Vector。
1. List接口常用方法:
- 增:add(Object o)
- 删:remove(int index)/remove(Object o)
- 改:set(int index, Object o)
- 查:get(int index)
- 插:add(int index, Object o)
- 长度:size()
- 遍历:
|--- Iterator迭代器
|--- for
|--- foreach
1 public class ListTest { 2 @Test 3 public void test1(){ 4 ArrayList list = new ArrayList(); 5 list.add(123); 6 list.add("A"); 7 list.add(456); 8 System.out.println("原始:" + list); 9 10 //void add(int index, Object ele):在index位置插入ele元素 11 list.add(0,"B"); 12 System.out.println("add(0,B):" + list); 13 14 //boolean addAll(int index, Collection eles):从index位置开始将eles中的所有元素添加进来 15 List list1 = Arrays.asList(1,2,3); 16 list.addAll(2,list1); 17 System.out.print("list1" + list1 + "*** "); 18 System.out.println("addAll(2,list1):" + list); 19 20 //Object get(int index):获取指定index位置的元素 21 System.out.println(list.get(0)); 22 } 23 24 @Test 25 public void test2(){ 26 ArrayList list = new ArrayList(); 27 list.add(456); 28 list.add(123); 29 list.add("A"); 30 list.add(456); 31 System.out.println("原始:" + list); 32 33 //int indexOf(Object obj):返回obj在集合中首次出现的位置,没有返回-1 34 System.out.println(list.indexOf("A"));//2 35 36 //int lastIndexOf(Object obj):返回obj在当前集合中最后一次出现的位置 37 System.out.println(list.lastIndexOf(456));//3 38 39 //Object remove(int index):移除指定index位置的元素,并返回此元素 40 System.out.println(list.remove(0)); 41 System.out.println("remove 0 后:" + list); 42 43 //Object set(int index, Object ele):设置指定index位置的元素为ele,并返回index处的元素 44 System.out.println(list.set(0,567)); 45 System.out.println("set(0,567)后:" + list); 46 47 //List subList(int fromIndex, int toIndex):返回从fromIndex到toIndex位置的子集合,左闭右开 48 System.out.println("subList(0,2): " + list.subList(0,2)); 49 System.out.println("list: " + list); 50 } 51 52 //遍历 53 @Test 54 public void test3(){ 55 ArrayList list = new ArrayList(); 56 list.add(456); 57 list.add(123); 58 list.add("A"); 59 list.add(456); 60 61 //Iterator迭代器 62 Iterator iterator = list.iterator(); 63 while(iterator.hasNext()) 64 System.out.println(iterator.next()); 65 System.out.println(); 66 67 //foreach 68 for(Object o: list){ 69 System.out.println(o); 70 } 71 System.out.println(); 72 73 //for 74 for(int i=0;i) 75 System.out.println(list.get(i)); 76 } 77 }
2. List的实现类ArrayList:ArrayList 是 List 接口的典型实现类、主要实现类,非线程安全,效率高,底层使用Object数组存储。
3. List的实现类LinkedList:对于频繁的插入或删除元素的操作,建议使用LinkedList类,效率较高,底层是双向链表,新增如下方法:
- void addFirst(Object obj)
- void addLast(Object obj)
- Object getFirst()
- Object getLast()
- Object removeFirst()
- Object removeLast()
4. List的实现类Vector:Vector 是一个古老的集合,JDK1.0就有了。大多数操作与ArrayList相同,区别之处在于Vector是线程安全的。
面试题:请问ArrayList/LinkedList/Vector的异同?谈谈你的理解?ArrayList底层是什么?扩容机制?Vector和ArrayList的最大区别?
ArrayList和LinkedList的异同:
- 二者都线程不安全,相对线程安全的Vector,执行效率高。
- 此外,ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构。对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。对于新增和删除操作add(特指插入)和remove,LinkedList比较占优势,因为ArrayList要移动数据。
ArrayList和Vector的区别:
- Vector和ArrayList几乎是完全相同的,唯一的区别在于Vector是同步类(synchronized),属于强同步类。因此开销就比ArrayList要大,访问要慢。正常情况下,大多数的Java程序员使用ArrayList而不是Vector,因为同步完全可以由程序员自己来控制。
- Vector每次扩容请求其大小的2倍空间,而ArrayList是1.5倍。Vector还有一个子类Stack。
四、Collection子接口——Set:Set接口是Collection的子接口,set接口没有提供额外的方法,Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个Set 集合中,则添加操作失败。Set 判断两个对象是否相同不是使用 == 运算符,而是根据 equals() 方法。
1. Set的实现类HashSet:HashSet 是 Set 接口的典型实现,大多数时候使用 Set 集合时都使用这个实现类。HashSet 按 Hash 算法来存储集合中的元素,因此具有很好的存取、查找、删除性能。
HashSet 具有以下特点:
- 不能保证元素的排列顺序
- HashSet 不是线程安全的
- 集合元素可以是 null
HashSet 集合判断两个元素相等的标准:两个对象通过 hashCode() 方法比较相等,并且两个对象的 equals() 方法返回值也相等。因此对于存放在Set容器中的对象,对应的类一定要重写equals()和hashCode(Objectobj)方法,以实现对象相等规则。即:“相等的对象必须具有相等的散列码”。
添加元素的过程,以HashSet为例:首先利用hash值确定index,若此index上有元素:
- hash值不同,添加成功
- hash值相同,调用该对象所在类的equals方法
- true:添加失败
- false:添加成功
2. Set的实现类LinkedHashSet:是 HashSet 的子类,根据元素的 hashCode 值来决定元素的存储位置,但它同时使用双向链表维护元素的次序,这使得元素看起来是以插入顺序保存的。LinkedHashSet插入性能略低于 HashSet,但在迭代访问 Set 里的全部元素时有很好的性能。
1 @Test 2 public void test2(){ 3 Set set = new LinkedHashSet(); 4 set.add(123); 5 set.add(456); 6 set.add("A"); 7 set.add(new Integer(789)); 8 9 Iterator iterator = set.iterator(); 10 while(iterator.hasNext()) 11 System.out.println(iterator.next()); 12 }
3. Set的实现类TreeSet:是 SortedSet 接口的实现类,TreeSet 可以确保集合元素处于排序状态,使用红黑树结构存储数据。新增如下方法:
- Comparator comparator()
- Object first()
- Object last()
- Object lower(Object e)
- Object higher(Object e)
- SortedSet subSet(fromElement, toElement)
- SortedSet headSet(toElement)
- SortedSet tailSet(fromElement)
3.1 自然排序:TreeSet 会调用集合元素的 compareTo(Object obj) 方法来比较元素之间的大小关系,然后将集合元素按升序(默认情况)排列。因此如果试图把一个对象添加到 TreeSet 时,则该对象的类必须实现 Comparable接口。向 TreeSet 中添加元素时,只有第一个元素无须比较compareTo()方法,后面添加的所有元素都会调用compareTo()方法进行比较。因为只有相同类的两个实例才会比较大小,所以向 TreeSet 中添加的应该是同一个类的对象。对于 TreeSet 集合而言,它判断两个对象是否相等的唯一标准是:两个对象通过 compareTo(Object obj) 方法比较返回值,不再是equals方法。
1 public class TreeSetTest { 2 @Test 3 public void test2(){ 4 TreeSet set = new TreeSet(); 5 set.add(new User("Amy",12)); 6 set.add(new User("Bob",13)); 7 set.add(new User("Emily", 14)); 8 set.add(new User("Dean", 15)); 9 set.add(new User("Dean", 16)); 10 11 Iterator iterator = set.iterator(); 12 while(iterator.hasNext()) 13 System.out.println(iterator.next()); 14 } 15 } 16 17 class User implements Comparable{ 18 private String name; 19 private int age; 20 21 public User() { 22 } 23 24 public User(String name, int age) { 25 this.name = name; 26 this.age = age; 27 } 28 29 public String getName() { 30 return name; 31 } 32 33 public void setName(String name) { 34 this.name = name; 35 } 36 37 public int getAge() { 38 return age; 39 } 40 41 public void setAge(int age) { 42 this.age = age; 43 } 44 45 @Override 46 //按照姓名从大到小排列,年龄从小到大 47 public int compareTo(Object o) { 48 if(o instanceof User){ 49 User user = (User)o; 50 int compare = -this.name.compareTo(user.name); 51 if(compare == 0){ 52 return Integer.compare(this.age, user.age); 53 }else 54 return compare; 55 56 }else{ 57 throw new RuntimeException("输入的类型不匹配"); 58 } 59 } 60 61 /* 62 @Override 63 //按照姓名从小到大排列 64 public int compareTo(Object o) { 65 if(o instanceof User){ 66 User user = (User)o; 67 return this.name.compareTo(user.name); 68 }else{ 69 throw new RuntimeException("输入的类型不匹配"); 70 } 71 } 72 */ 73 74 @Override 75 public String toString() { 76 return "name: " + name + ", age: " + age; 77 } 78 }
3.2 定制排序:在定制排序中,比较两个对象是否相同的标准为:compare方法的返回值,不再是equals方法。
1 @Test 2 public void test3(){ 3 Comparator com = new Comparator() { 4 //按照年龄从小到大,年龄一样的数据只要一个 5 @Override 6 public int compare(Object o, Object t1) { 7 if(o instanceof User && t1 instanceof User){ 8 User u1 = (User)o; 9 User u2 = (User)t1; 10 return Integer.compare(u1.getAge(), u2.getAge()); 11 }else{ 12 throw new RuntimeException("输入的数据类型不匹配"); 13 } 14 } 15 }; 16 17 TreeSet set = new TreeSet(com); 18 set.add(new User("Amy",12)); 19 set.add(new User("Bob",12)); 20 set.add(new User("Emily", 14)); 21 set.add(new User("Dean", 15)); 22 set.add(new User("Dean", 16)); 23 24 Iterator iterator = set.iterator(); 25 while(iterator.hasNext()) 26 System.out.println(iterator.next()); 27 }
五、Map接口:用于保存具有映射关系的数据:key-value,类似与高中讲的函数的概念。
0. Map结构的理解:
- key:无序、不可重复,使用Set存储所有的key;--->要求key所在的类重写equals和hashcode方法(以HashMap为例的)
- value:无序、可重复,使用Collection存储所有的value。--->要求value所在的类重写equals方法
- 一个key-value对构成了一个Entry对象。entry是无序、不可重复的。
1. Map接口常用方法:
1 public class MapTest { 2 @Test 3 //增删改 4 public void test1(){ 5 //put 6 HashMap hashMap = new HashMap(); 7 hashMap.put("AA",123); 8 hashMap.put("BB",456); 9 hashMap.put("CC",789); 10 hashMap.put("AA",101); 11 12 System.out.println(hashMap);//{AA=101, BB=456, CC=789}相当于原有的123被改为101 13 14 //putAll 15 HashMap hashMap1 = new HashMap(); 16 hashMap1.put("DD",102); 17 hashMap1.putAll(hashMap); 18 System.out.println(hashMap1); 19 20 //remove(key),返回对应key的value并删除该entry 21 System.out.println(hashMap.remove("AA")); 22 System.out.println(hashMap); 23 24 //clear 25 hashMap1.clear(); 26 System.out.println(hashMap1); 27 } 28 29 @Test 30 //查询 31 public void test2(){ 32 HashMap hashMap = new HashMap(); 33 hashMap.put("AA",123); 34 hashMap.put("BB",456); 35 hashMap.put("CC",789); 36 37 //get 38 System.out.println(hashMap.get("AA")); 39 40 //containsKey 41 System.out.println(hashMap.containsKey("DD")); 42 43 //containsValue 44 System.out.println(hashMap.containsValue(789)); 45 46 //size 47 System.out.println(hashMap.size()); 48 49 //isEmpty 50 System.out.println(hashMap.isEmpty()); 51 } 52 53 @Test 54 //遍历 55 public void test3(){ 56 HashMap hashMap = new HashMap(); 57 hashMap.put("AA",123); 58 hashMap.put("BB",456); 59 hashMap.put("CC",789); 60 61 //keySet,返回一个Set 62 Set set = hashMap.keySet(); 63 Iterator iterator = set.iterator(); 64 while(iterator.hasNext()) 65 System.out.println(iterator.next()); 66 67 //values,返回一个Collection 68 Collection values = hashMap.values(); 69 Iterator iterator2 = values.iterator(); 70 while(iterator2.hasNext()) 71 System.out.println(iterator2.next()); 72 73 //entrySet,返回一个Set 74 Set set1 = hashMap.entrySet(); 75 Iterator iterator1 = set1.iterator(); 76 while(iterator1.hasNext()){ 77 Object object = iterator1.next(); 78 Map.Entry entry = (Map.Entry) object; 79 System.out.println(entry.getKey() + "--->" + entry.getValue()); 80 } 81 } 82 }
2. HashMap:作为Map的主要实现类,线程不安全,效率高,可以存储null,底层是数组+链表(jdk8及以后+红黑树)
3. LInkedHashMap:作为HashMap的子类,保证了遍历map元素时按照添加时的顺序遍历。对于频繁遍历的操作,此类执行的效率高于HashMap
4. TreeMap:保证按照添加的key-value对进行排序,实现排序遍历。此时考虑key的自然/定制排序,底层使用红黑树。要求都是同一个类
1 public class TreeMapTest { 2 3 @Test 4 //自然排序 5 public void test1(){ 6 TreeMap map = new TreeMap(); 7 User u1 = new User("Tom",23); 8 User u2 = new User("Jack",12); 9 User u3 = new User("Bob",21); 10 11 map.put(u1, 90); 12 map.put(u2, 81); 13 map.put(u3, 62); 14 15 Set set1 = map.entrySet(); 16 Iterator iterator1 = set1.iterator(); 17 while(iterator1.hasNext()){ 18 Object object = iterator1.next(); 19 Map.Entry entry = (Map.Entry) object; 20 System.out.println(entry.getKey() + "--->" + entry.getValue()); 21 } 22 } 23 24 @Test 25 //定制排序:定制按照年龄排序 26 public void test2(){ 27 TreeMap map = new TreeMap(new Comparator() { 28 @Override 29 public int compare(Object o1, Object o2) { 30 if(o1 instanceof User && o2 instanceof User){ 31 User u1 = (User)o1; 32 User u2 = (User)o2; 33 return Integer.compare(u1.getAge(), u2.getAge()); 34 } 35 throw new RuntimeException("输入的类型不匹配"); 36 } 37 }); 38 User u1 = new User("Tom",23); 39 User u2 = new User("Jack",12); 40 User u3 = new User("Bob",21); 41 42 map.put(u1, 90); 43 map.put(u2, 81); 44 map.put(u3, 62); 45 46 Set set1 = map.entrySet(); 47 Iterator iterator1 = set1.iterator(); 48 while(iterator1.hasNext()){ 49 Object object = iterator1.next(); 50 Map.Entry entry = (Map.Entry) object; 51 System.out.println(entry.getKey() + "--->" + entry.getValue()); 52 } 53 } 54 }
5. Hashtable:作为古老的实现类,线程安全的,效率低,不能存储null
|--- Properties:常用来处理配置文件,key和value都是String类型。
1 public class PropertiesTest { 2 public static void main(String[] args) throws IOException { 3 Properties properties = new Properties(); 4 5 FileInputStream fis = new FileInputStream("jdbc.properties"); 6 properties.load(fis); 7 8 String name = properties.getProperty("name"); 9 String password = properties.getProperty("password"); 10 11 System.out.println(name + " " + password); 12 } 13 }
六、Collections工具类:Collections 是一个操作 Set、List 和 Map 等集合的工具类
1. 排序操作:(均为static方法)
- reverse(List):反转 List 中元素的顺序
- shuffle(List):对 List 集合元素进行随机排序
- sort(List):根据元素的自然顺序对指定 List 集合元素按升序排序
- sort(List,Comparator):根据指定的 Comparator 产生的顺序对 List 集合元素进行排序
- swap(List,int, int):将指定 list 集合中的 i 处元素和 j 处元素进行交换
2. 查找、替换:
- Object max(Collection):根据元素的自然顺序,返回给定集合中的最大元素
- Object max(Collection,Comparator):根据 Comparator 指定的顺序,返回给定集合中的最大元素
- Object min(Collection)
- Object min(Collection,Comparator)
- int frequency(Collection,Object):返回指定集合中指定元素的出现次数
- void copy(List dest,List src):将src中的内容复制到dest中
- boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替换List 对象的所有旧值
1 public class CollectionsTest { 2 @Test 3 public void test(){ 4 List list = new ArrayList(); 5 list.add(1); 6 list.add(2); 7 list.add(3); 8 9 List list1 = Arrays.asList(new Object[list.size()]); 10 Collections.copy(list1, list); 11 System.out.println(list1); 12 } 13 }