Java集合详解

内容:

1、List相关

2、Set相关

3、Collection总结

4、Map相关

5、其他

 

 

 

1、List相关

(1)List集合存储数据的结构

List接口下有很多个集合,它们存储元素所采用的结构方式是不同的,这样就导致了这些集合有它们各自的特点,

在不同的环境下进行使用。数据存储的常用结构有:堆栈、队列、数组、链表

堆栈(栈)的特点:

  • 先进后出
  • 栈的入口和出口都是栈的顶端位置
  • 压栈(压入元素)、弹栈(弹出元素)

队列的特点:

  • 先进先出
  • 队列的入口、出口各占一侧

数组的特点:

  • 查找元素快(通过索引,可以快速访问指定位置的元素)
  • 增删元素慢(需要移动元素)

链表的特点:

  • 多个节点之间,通过地址进行连接
  • 查找元素慢:想查找某个元素,需要通过连接的节点,依次向后查找指定元素
  • 增删元素快:只需修改连接下个元素的地址

 

(2)List接口的特点及其实现类

List接口的特点:

  • 有下标
  • 有序的(存和取的顺序一致)
  • 可重复

List接口实现类:ArrayList、LinkedList、Vector

  • ArrayList:底层采用数组结构,查询快,增删慢  =》线程不安全
  • LinkedList:底层采用链表结构,查询慢,增删快  =》线程不安全
  • Vector:底层采用数组结构,查询快,增删慢  =》线程安全

List接口的方法:

  • 增:add(E e)  add(int index, E e)
  • 删:remove(Object obj) remove(int index)
  • 改:set(int index, E e)
  • 查:get(int index)
  • 其他方法:size()、clear()、contains(Object obj)、toArray()、iterator()、isEmpty()

实现类中的方法:

  • ArrayList:方法基本和List中定义的一模一样
  • LinkedList:除了和List接口中一样的方法之外,还有一些特有的方法

 

(3)LinkedList集合

LinkedList集合数据存储的结构是链表结构。方便元素添加、删除的集合。实际开发中对一个集合元素的添加与删除

经常涉及到首尾操作,而LinkedList提供了大量首尾操作的方法。如下图

LinkedList是List的子类,List中的方法LinkedList都是可以使用,这里就不做详细介绍,我们只需要了解LinkedList的特有方法即可。

在开发时,LinkedList集合也可以作为堆栈,队列的结构使用

使用实例:

 1 public class useLinkedList {
 2     public static void main(String[] args) {
 3         LinkedList<String> link = new LinkedList<String>();
 4         // 添加元素
 5         link.addFirst("abc1");
 6         link.addFirst("abc2");
 7         link.addFirst("abc3");
 8         // 获取元素
 9         System.out.println(link.getFirst());    // abc3
10         System.out.println(link.getLast());        // abc1
11         // 删除元素
12         System.out.println(link.removeFirst());    // abc3
13         System.out.println(link.removeLast());    // abc1
14 
15         while (!link.isEmpty()) { // 判断集合是否为空
16             System.out.println(link.pop()); // 弹出集合中的栈顶元素
17             // abc2
18         }
19     }
20 }

 

 

2、Set相关

(1)Set接口的特点及其实现类

Set接口的特点:

  • 无下标
  • 无序的(无序是指存和取的顺序不一定一致,LinkedHashSet和TreeSet除外)
  • 不可重复

Set接口实现类:HashSet、LinkedHashSet、TreeSet

  • HashSet:底层采用哈希表结构,查询快,增删快,无序的
  • LinkedHashSet:底层采用链表+哈希表结构,查询快,增删快,有序的 
  • TreeSet:底层采用红黑树结构,查询快,增删快, 有序的 

Set接口的方法:没有特有方法,基本和父接口Collection类一模一样

实现类中的方法:实现类中的方法基本和Set一模一样

 

(2)哈希相关

对象的哈希值:任何对象都有一个哈希值,哈希值是对象的一个数字表示  

对象的字符串表示:toString方法,默认表示格式:包名.类名@地址值(这里的地址值实际上是哈希值的16进制)

如何获取对象的哈希值 =》hashCode方法(默认按地址值计算)

什么是哈希表:

哈希表底层使用的也是数组机制,数组中也存放对象,而这些对象往数组中存放时的位置比较特殊,当需要把这些

对象给数组中存放时,那么会根据这些对象的特有数据结合相应的算法,计算出这个对象在数组中的位置,然后把

这个对象存放在数组中。而这样的数组就称为哈希数组,即就是哈希表

hashCode方法和equals方法:

当向哈希表中存放元素时,需要根据元素的特有数据结合相应的算法,这个算法就是Object类中的hashCode方法。

在给哈希表中存放对象时,会调用对象的hashCode方法,算出对象在表中的存放位置,这里需要注意,如果两个对象

hashCode方法算出结果一样,这样现象称为哈希冲突,这时会调用equals方法,比较这两个对象是不是同一个对象,

如果equals方法返回true,那么就不会把第二个对象存放在哈希表中,如果返回false,就会把这个值存放在哈希表中。

 1 public class StringHashCodeDemo {
 2     public static void main(String[] args) {
 3         String s1 = new String("abc");
 4         String s2 = new String("abc");
 5     
 6         System.out.println(s1==s2);        // false
 7         System.out.println(s1.hashCode()==s2.hashCode());    // true
 8         System.out.println(s1.equals(s2));                    // true
 9         
10     }
11 }

注意:String类重写了hashCode方法,按照自己的方式计算(只要字符串内容一样哈希值一定相同)

总结:保证HashSet集合元素的唯一,其实就是根据对象的hashCode和equals方法来决定的。如果我们往集合中存放自定义

的对象,那么保证其唯一,就必须复写hashCode和equals方法建立属于当前对象的比较方式。

 

哈希表结构判断元素是否重复的原理:

hashCode():先判断新元素的哈希值是否和旧元素哈希值相同,如果都不相同直接判断不重复,添加

equals():再调用新元素和哈希值相同的旧元素的equals方法,如果返回true判定重复元素,不添加,否则添加(不重复)

 

(3)Set使用实例

 1 public class HashSetDemo {
 2 
 3     public static void main(String[] args) {
 4         // 创建HashSet对象
 5         HashSet<String> hs = new HashSet<String>();
 6         // 给集合中添加自定义对象
 7         hs.add("zhangsan");
 8         hs.add("lisi");
 9         hs.add("wangwu");
10         hs.add("zhangsan");
11         System.out.println(hs);
12         // 判断是否含有某个元素
13         System.out.println(hs.contains("lisi"));    // true
14         // 取出集合中的每个元素
15         Iterator<String> it = hs.iterator();
16         while (it.hasNext()) {
17             String s = it.next();
18             System.out.println(s);
19         }
20     }
21 }

 

 

3、Collection总结

(1)Collection

Collection分类:

  • List 可以存储重复元素,有序的(元素存取顺序),有索引  =》ArrayList、LinkedList
  • Set 不能存储重复元素,无序的(元素存取顺序,LinkedHashSet是有序的),无索引 =》HashSet、LinkedHashSet

Collection方法:

  • boolean add(Object e)         把给定的对象添加到当前集合中
  • void clear()                           清空集合中所有的元素
  • boolean remove(Object o)   把给定的对象在当前集合中删除
  • boolean contains(Object o)   判断当前集合中是否包含给定的对象
  • boolean isEmpty()                判断当前集合是否为空
  • Iterator iterator()                   迭代器,用来遍历集合中的元素的
  • int size()                                返回集合中元素的个数
  • Object[] toArray()                  把集合中的元素,存储到数组中
  • Iterator :                                     迭代器
  • Object next()                        返回迭代的下一个元素
  • boolean hasNext()               如果仍有元素可以迭代,则返回 true。

 

(2)List和Set

List与Set集合的区别:

  • List是一个有序的集合(元素存与取的顺序相同),可以存储重复的元素                       
  • Set是一个无序的集合(元素存与取的顺序可能不同),不能存储重复的元素

List集合中的特有方法(下标):

  • void add(int index, Object element) 将指定的元素,添加到该集合中的指定位置上
  • Object get(int index)返回集合中指定位置的元素
  • Object remove(int index) 移除列表中指定位置的元素, 返回的是被移除的元素
  • Object set(int index, Object element)用指定元素替换集合中指定位置的元素,返回值的更新前的元素

 

List和Set的实现类:

ArrayList:

        底层数据结构是数组,查询快,增删慢

        线程不安全,效率高

LinkedList:

        底层数据结构是链表,查询慢,增删快

        线程不安全,效率高

Vector:

        底层数据结构是数组,查询快,增删慢

        线程安全,效率不高

HashSet:

        元素唯一不能重复

        底层结构是 哈希表结构

        元素的存与取的顺序不能保证一致

LinkedHashSet:

        元素唯一不能重复

        底层结构是 链表结构+哈希表结构

       元素的存与取的顺序一致

 

(3)Set中元素的唯一性

如何保证元素的唯一的:重写hashCode() 与 equals()方法

 

(4)contains

ArrayList的contains方法:

调用时,会使用传入的元素的equals方法依次与集合中的旧元素所比较,从而根据返回的布尔值判断

是否有重复元素。此时,当ArrayList存放自定义类型时,由于自定义类型在未重写equals方法前,判断是否重复的依据是地址值,

所以如果想根据内容判断是否为重复元素,需要重写元素的equals方法 

HashSet的contains方法:

与add方法同理,先判断哈希值再使用equals方法判断,只要旧元素和判断的元素的哈希值相同并且equals方法为true才判定包含

 

 

4、Map相关

(1)Map集合的特点

  • Map集合和Collection集合没有继承关系,所以不能直接用迭代器
  • Collection集合每一个元素都是单独存在,而Map集合中的每一个元素都是成对存在
  • Map<K, V> 两个泛型,K代表键的类型,V代表值的类型,K和V必须是引用类型
  • 在Map集合的元素中键是唯一的,值是可以重复的

 

(2)Map接口常用集合概述(实现类)

通过查看Map接口描述,看到Map有多个子类,这里我们主要讲解常用的HashMap集合、LinkedHashMap集合:

HashMap<K,V>:存储数据采用的哈希表结构,元素的存取顺序不能保证一致。由于要保证键的唯一、不重复,

需要重写键的hashCode()方法、equals()方法。

LinkedHashMap<K,V>:HashMap下有个子类LinkedHashMap,存储数据采用的哈希表结构+链表结构。通过链表结构

可以保证元素的存取顺序一致;通过哈希表结构可以保证的键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。

 

注:

  • 当给HashMap中存放自定义对象时,如果自定义对象作为key存在,这时要保证对象唯一,必须复写对象的hashCode和equals方法
  • 如果要保证map中存放的key和取出的顺序一致,可以使用LinkedHashMap集合来存放

 

(3)Map接口中的常用方法

 1 public class HashMapDemo {
 2     public static void main(String[] args) {
 3         // 创建Map对象
 4         Map<String, String> map = new HashMap<String, String>();
 5         // 给map中添加元素
 6         map.put("星期一", "Monday");
 7         map.put("星期日", "Sunday");
 8         System.out.println(map); // {星期日=Sunday, 星期一=Monday}
 9 
10         // 当给Map中添加元素,会返回key对应的原来的value值,若key没有对应的值,返回null
11         System.out.println(map.put("星期一", "Mon")); // Monday
12         System.out.println(map); // {星期日=Sunday, 星期一=Mon}
13 
14         // 根据指定的key获取对应的value
15         String en = map.get("星期日");
16         System.out.println(en); // Sunday
17 
18         // 根据key删除元素,会返回key对应的value值
19         String value = map.remove("星期日");
20         System.out.println(value); // Sunday
21         System.out.println(map); // {星期一=Mon}
22     }
23 }

 

(4)Map集合遍历方式

键找值方式:即通过元素中的键,获取键所对应的值

  • KeySet():获取Map集合中的所有键
  • get(Object key):通过指定的键从map集合中找出相应的值

 

1 for(String key:map.keySet()){
2     System.out.println(key + " = " + map.get(key));
3 }

 

EntrySet方式(键值对方式):

在Map类设计时,提供了一个嵌套接口:Entry。Entry将键值对的对应关系封装成了对象。即键值对对象,这样我们在遍历Map集合时,

就可以从每一个键值对(Entry)对象中获取对应的键与对应的值:

 1 Set<Map.Entry<String, String>> entrySet = map.entrySet();
 2 for (Map.Entry<String, String> entry : entrySet) {
 3     Stringkey = entry.getKey();
 4     String value = entry.getValue();
 5     System.out.println(key+"....."+value);
 6 }
 7 
 8 // 上面的代码也可以简化成这样:
 9 for (Map.Entry<String, String> entry : map.entrySet()) {
10     Stringkey = entry.getKey();
11     String value = entry.getValue();
12     System.out.println(key+"....."+value);
13 }

 

(5)LinkedHashMap

HashMap保证成对元素唯一,并且查询速度很快,可是成对元素存放进去是没有顺序的,那么我们要保证有序,还要速度快怎么办呢?

在HashMap下面有一个子类LinkedHashMap,它是链表和哈希表组合的一个数据存储结构,它可以保证有序

 1 import java.util.*;
 2 import java.util.Map.Entry;
 3 
 4 public class LinkedHashMapDemo {
 5     public static void main(String[] args) {
 6         Map<String, String> map = new LinkedHashMap<String, String>();
 7 
 8         map.put("1", "a");
 9         map.put("2", "b");
10         map.put("3", "c");
11 
12         for (Entry<String, String> entry : map.entrySet()) {
13             System.out.println(entry.getKey() + "  " + entry.getValue());
14         }
15         // 输出结果:
16         // 1 a
17         // 2 b
18         // 3 c
19     }
20 }

 

 

5、其他

(1)Properties类介绍

Properties类表示了一个持久的属性集。Properties可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。

特点:

  • 是Hashtable的子类,map集合中的方法都可以用
  • 该集合没有泛型。键值都是字符串
  • 是一个可以持久化的属性集。键值可以存储到集合中,也可以存储到持久化设备上。键值的来源也可以是持久化设备。
  • 有和流技术相结合的方法。

特有的方法:

  • public String getProperty(String key)        功能就是Map中的get方法
  • public Object setProperty(String key, String value)     功能就是Map中的put方法
  • public Set<String> stringPropertyNames()       返回此属性列表中的键集(Map中的KeySet方法)

和流技术结合的方法:

  • store方法:保存数据到文件
  • load方法:加载数据
 1 import java.io.*;
 2 import java.util.Properties;
 3 
 4 public class PropertiesDemo {
 5     public static void main(String[] args) throws IOException {
 6         // 创建对象
 7         Properties ps = new Properties();
 8         // 添加数据
 9         ps.setProperty("test", "18");
10         ps.setProperty("test2", "16");
11         ps.setProperty("test3", "18");
12         // 讲ps的数据持久化到文件中
13         ps.store(new FileWriter("test.properties"), "author is wyb");
14 
15         Properties t = new Properties();
16         // 从文件中读取数据到t中
17         t.load(new FileReader("test.properties"));
18         // 遍历
19         for (String key : t.stringPropertyNames()) {
20             System.out.println(key + " = " + t.getProperty(key));
21         }
22     }
23 }

 

(2)可变参数

 1 public class ParamDemo {
 2     public static void main(String[] args) {
 3         int[] arr = {21,89,32};
 4         int sum = add(arr);
 5         System.out.println(sum);
 6         sum = add(21, 89, 32);  // 可变参数调用形式(可以传任意多个参数)
 7         System.out.println(sum);
 8         
 9     }
10 
11     //JDK1.5之后写法
12     public static int add(int...arr){
13         int sum = 0;
14         for (int i = 0; i < arr.length; i++) {
15             sum += arr[i];
16         }
17         return sum;
18     }
19 
20     //原始写法
21     /*
22     public static int add(int[] arr) {
23         int sum = 0;
24         for (int i = 0; i < arr.length; i++) {
25             sum += arr[i];
26         }
27         return sum;
28     }
29     */
30 }

 

(3)Collections介绍

Collections是集合工具类(不能实例化),用来对集合进行操作。部分方法如下:

1 // 排序:
2 // 排序前元素list集合元素 [33,11,77,55]
3 Collections.sort( list );
4 // 排序后元素list集合元素 [11,33,55,77]
5 
6 // 打乱顺序:
7 // list集合元素 [11,33,55,77]
8 Collections.shuffle( list );
9 // 使用shuffle方法后,集合中的元素就会被打乱,每次执行该方法,集合中存储的元素位置都会随机打乱

 

posted @ 2019-02-03 15:27  woz333333  阅读(227)  评论(0编辑  收藏  举报