Java入门笔记 09-集合

一、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<list.size();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 }
posted @ 2020-02-18 16:09  HankBernstein  阅读(179)  评论(0编辑  收藏  举报