JavaSE复习总结之集合

x33g5p2x  于2022-03-28 转载在 Java  
字(10.8k)|赞(0)|评价(0)|浏览(215)

集合概述

集合实际上就是一个容器。可以来容纳其它类型的数据。数组其实就是一个集合。

Java 集合主要有 3 种重要的类型:

  • List:是一个有序集合,可以放重复的数据
  • Set:是一个无序集合,不允许放重复的数据
  • Map:是一个无序集合,集合中包含一个键对象(Key),一个值对象(Value)

Collection(单列集合)

Collection是最基本的集合接口。它继承自Iterable接口,Iterable表示可迭代的,所以所有的集合元素都是可迭代可遍历的。它有两个子接口:

  • List接口:有序可重复
  • Set接口:无序不可重复

Collection中能存放什么元素 ?

没有使用泛型之前,Collection中可以存储Object的所有子类型。
使用了泛型之后,Collection中只能存储某个具体的类型。

Collection中的常用方法

返回值类型方法名描述
booleanadd(Object e)向集合中添加元素
intsize()获取集合中元素的个数
voidclear()清空集合
booleancontains(Object o)判断当前集合中是否包含元素o
booleanremove(Object o)删除集合中的某个元素
booleanisEmpty()判断该集合中元素的个数是否为0
Object[]toArray()调用这个方法可以把集合转换成数组

注意:集合不能直接存储基本数据类型,另外集合也不能直接存储java对象,集合当中存储的都是java对象的内存地址(或者说集合中存储的是引用)

//这里存进去的并不是int类型的1200
//这里使用了自动装箱机制 Integer x = new Integer(1200);
c.add(1200);

集合的迭代

Iterator常用方法

返回值类型方法名描述
booleanhasNext()如果仍有元素可迭代就返回true
Objectnext()返回迭代的下一个元素
voidremove()从集合中移除next()方法返回的最后一个元素

注意:在迭代集合元素的过程中,不能调用集合对象的remove方法删除元素。否则会造成java.util.ConcurrentModificationException异常。正确做法是使用迭代器Iterator提供的remove方法

public static void main(String[] args) {
	Collection c1  = new ArrayList();  // 创建集合对象
	c1.add(1);// 添加元素
	c1.add(2);// 添加元素
	c1.add(3);// 添加元素
	c1.add(4);// 添加元素
	c1.add(1);// 添加元素
	// 获取集合迭代器
	Iterator it = c1.iterator();
	while(it.hasNext()){
		Object obj = it.next();
		//c1.remove(obj);删除元素之后,集合的结构发生了变化,但是循环下一次的时候并没有重新获取迭代器
		it2.remove();// 迭代器去删除时,会自动更新迭代器,并且更新集合
		System.out.println(obj);
	}
}

List接口

List集合中的常用方法

返回值类型方法名描述
voidadd(int index,Object element)将元素element插入到List集合的index索引处
Objectget(int index)返回列表index索引处的元素
Objectremove(int index)删除列表index索引处的元素
intindexOf(Object o)返回对象o在List集合中出现的位置索引
intLastIndexOf(Object o)返回对象o在List集合中最后一次出现的位置索引
ListsubList(int fromIndex,int toIndex)返回从索引fromIndex(包括)到toIndex处(不包括)处的子集合

ArrayList

ArrayList集合底层是一个Object[]数组,默认初始化容量10。ArrayList集合是非线程安全的

  • 数组优点: 检索效率比较高。
  • 数组缺点:
    1、 随机增删元素效率比较低。向数组末尾添加元素效率不受影响
    2、另外数组无法存储大数据量。(很难找到一块非常巨大的连续的内存空间。)
public class ArrayListTest{
    public static void main(String[] args) {
        //List list = new ArrayList();默认初始化容量是10
        List list = new ArrayList(4); // 指定初始化容量4
        // 集合的size()方法是获取当前集合中元素的个数。不是获取集合的容量。
        System.out.println(list1.size()); // 0
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        // 再加一个元素
        list.add(5);//数组自动扩容,增长到原容量的1.5倍
    }
    //第一种遍历方式:fori
	for(int i = 0; i <list1.size(); i++){
		Object elem = list1.get(i);
		System.out.println(elem);
	}
	//第一种遍历方式:foreach
	for (Object elem : list1) {
		System.out.println(elem);
	}
	//第一种遍历方式:使用迭代器
	Iterator iterator = list1.iterator();
	while (iterator.hasNext()){
		Object next = iterator.next();
		System.out.println(next);
	}
}

注意:并不是一创建ArrayList容器对象就初始化容量。底层先创建了一个长度为0的数组,当添加第一个元素的时候,初始化容量10

LinkedList

LinkedList集合底层采用了双向链表的数据结构
LinkedList集合中常用的方法

返回值类型方法名描述
voidaddFirst(Object o)将元素o添加到集合的开头
voidaddLast(Object o)将元素o添加到集合的结尾
ObjectgetFirst()返回集合的首元素
ObjectgetLast()返回集合的尾元素
ObjectremoveFirst()移除并返回集合的首元素
ObjectremoveLast()移除并返回集合的尾元素
public class LinkedListTest01 {
    public static void main(String[] args) {
        // LinkedList集合底层也是有下标的。
        // LinkedList集合有初始化容量吗?没有。
        List<String> list = new LinkedList();
        list.add("a");
        list.add("b");
        list.add("c");
		//第一种遍历方式:fori
        for(int i = 0; i <list.size(); i++){
            String str = list.get(i);
            System.out.println(str);
        }
        //第一种遍历方式:foreach
        for (String str : list) {
            System.out.println(str);
        }
        //第一种遍历方式:使用迭代器
        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()){
            String nextStr = iterator.next();
            System.out.println(nextStr);
        }
    }
}
  • 链表的优点:
    由于链表上的元素在空间存储上内存地址不连续。所以随机增删元素的时候不会有大量元素位移,因此随机增删效率较高。在以后的开发中,如果遇到随机增删集合中元素的业务比较多时,建议使用LinkedList。
  • 链表的缺点:
    不能通过数学表达式计算被查找元素的内存地址,每一次查找都是从头节点开始遍历,直到找到为止。所以LinkedList集合检索/查找的效率较低。

Vector

  • 底层是数组
  • Vector初始化容量是10
  • 扩容为原容量的2倍
  • Vector底层是线程安全的
public class VectorTest {
    public static void main(String[] args) {
        // 创建一个Vector集合
        List vector = new Vector();
        vector.add(1);
        vector.add(2);
        vector.add(3);
        vector.add(4);
        vector.add(5);
        Iterator it = vector.iterator();
        while(it.hasNext()){
            Object obj = it.next();
            System.out.println(obj);
        }
}

如何将非线程安全的集合转换成线程安全的集合

List myList = new ArrayList(); // 非线程安全的。
// 变成线程安全的
Collections.synchronizedList(myList);
// myList集合就是线程安全的了。
myList.add("111");
myList.add("222");
myList.add("333");

Set接口

Set集合存储元素的特点:无序不可重复
Set集合没有下标不能使用fori的方式遍历

HashSet

HashSet集合在new的时候底层实际上new了一个HashMap集合,向HashSet集合中存放元素实际上存储到HashMap集合的key部分、HashMap集合底层是一个哈希表。

public class HashSetTest01 {
    public static void main(String[] args) {
        // 演示一下HashSet集合特点
        Set<String> hashSet= new HashSet<>();
        //String类已经重写了hashCode()方法和equals()方法
        hashSet.add("hello3");// 添加元素
        hashSet.add("hello4");
        hashSet.add("hello1");
        hashSet.add("hello2");
        hashSet.add("hello3");
        hashSet.add("hello3");
        hashSet.add("hello3");
        hashSet.add("hello3");
        //第一种遍历方式:foreach
        for(String s : hashSet){
            System.out.println(s);
        }
        //第二种遍历方式:迭代器
        Iterator<String> iterator = hashSet.iterator();
        while(iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }
}

【运行结果】

hello1
hello4
hello2
hello3

Process finished with exit code 0

【结论】
1、存储时顺序和取出的顺序不同。
2、不可重复。
3、放到HashSet集合中的元素实际上是放到HashMap集合的key部分了。

HashSet集合是如何保证添加元素时不出现重复的 ?
保证不重复的关键在于出入对象的hashCode()方法和equals()方法。向HashSet集合中存入对象时,首先调用对象的hashCode()方法获取对象的哈希值,然后根据哈希值计算处存储位置。如果该位置上没有元素就将元素存入,如果该位置上已有元素则调用equals()方法比较两个元素是否相同,如果不相同则通过探测再散列的方法找到一个新的位置将元素存入,如果相同就不存入元素

TreeSet

TreeSet集合在new的时候底层实际上new了一个TreeMap集合,向TreeSet集合中存放元素实际上存储到TreeMap集合的key部分。TreeMap集合底层是一个二叉树。
TreeSet集合存储元素特点:
1、无序不可重复的,但是存储的元素可以自动按照大小顺序排序!
2、无序:这里的无序指的是存进去的顺序和取出来的顺序不同。并且没有下标。

TreeSet中定义的方法

返回类型方法名描述
Objectfirst()返回集合中的最低元素
Objectlast()返回集合中的最高元素
Comparator<? super E>comparator()返回对此集合中元素进行排序的比较器
public class TreeSetTest01 {
    public static void main(String[] args) {
        // 创建集合对象
        Set<String> strs = new TreeSet<>();
        // 添加元素
        strs.add("A");
        strs.add("B");
        strs.add("Z");
        strs.add("Y");
        strs.add("Z");
        strs.add("K");
        for(String s : strs){
            System.out.print(s+" ");//从小到大自动排序
        }
    }
}

【输出结果】

A B K M Y Z

Process finished with exit code 0

TreeSet集合中自定义类型元素可排序的二种方式

//1、实现Comparable接口并且重写compareTo方法
public class Customer implements Comparable<Customer>{
    int age;
    public Customer(int age){
        this.age = age;
    }
    public int compareTo(Customer c) {
        return c.age - this.age;
    }
}
//2、使用比较器
public class TreeSetTest {
    public static void main(String[] args) {

        // 给构造方法传递一个比较器。(匿名内部类)也可以单独编写一个比较器
        TreeSet<Customer> customerList = new TreeSet<>(new Comparator<WuGui>() {
            @Override
            public int compare(Customer c1, Customer c2) {
                return c1.age - c2.age;
            }
        });

        customerList.add(new Customer(20));
        customerList.add(new Customer(30));
        customerList.add(new Customer(18));
        for(Customer customer: customerList){
            System.out.println(customer);
        }
    }
}

Comparable和Comparator怎么选择呢 ?

  • 当比较规则不会发生改变的时候,或者说当比较规则只有1个的时候,建议实Comparable接口。
  • 如果比较规则有多个,并且需要多个比较规则之间频繁切换,建议使用Comparator接口。

Map(双列集合)

  • Map和Collection没有继承关系
  • Map集合以key和value的方式存储数据:键值对
    key和value都是引用数据类型。
    key和value都是存储对象的内存地址。

Map接口中常用方法

返回值类型方法名描述
voidput(K key, V value)向Map集合中添加键值对
Objectget(Object key)通过key获取value
voidclear()清空Map集合
booleancontainsKey(Object key)判断Map中是否包含某个key
booleancontainsValue(Object value)判断Map中是否包含某个value
booleanisEmpty()判断Map集合中元素个数是否为0
Vremove(Object key)通过key删除键值对
intsize()获取Map集合中键值对的个数。
Collection<V>values()获取Map集合中所有的value,返回一个Collection
Set<K>keySet()获取Map集合所有的key(所有的键是一个set集合)
Set<Map.Entry<K,V>>entrySet()将Map集合转换成Set集合

Map集合的遍历

public class MapTest {
    public static void main(String[] args) {
        Map<Integer, String> map = new HashMap<>();
        map.put(1, "zhangsan");
        map.put(2, "lisi");
        map.put(3, "wangwu");
        map.put(4, "zhaoliu");
        
        // 第一种方式:获取所有的key,通过遍历key,来遍历value
        Set<Integer> keys = map.keySet();
        for(Integer key : keys){// foreach遍历,当然也可以使用迭代器遍历
            System.out.println(key + "=" + map.get(key));
        }
        
        // 第二种方式:Set<Map.Entry<K,V>> entrySet()
        // 这个方法是把Map集合直接全部转换成Set集合。
        // Set集合中元素的类型是:Map.Entry
        Set<Map.Entry<Integer,String>> set = map.entrySet();
        for(Map.Entry<Integer,String> node : set){// foreach遍历,当然也可以使用迭代器遍历
            System.out.println(node.getKey() + "--->" + node.getValue());
        }
    }
}

HashMap

  • HashMap集合底层是哈希表/散列表的数据结构
  • HashMap集合的key部分特点:无序,不可重复。 如果key重复了,value会覆盖
  • 放在HashMap集合key部分的元素其实就是放到HashSet集合中了
  • HashMap集合的默认初始化容量是16,默认加载因子是0.75
    这个默认加载因子是当HashMap集合底层数组的容量达到75%的时候,数组开始扩容,扩容2倍
  • HashMap集合初始化容量必须是2的倍数,这也是官方推荐的
  • 放在HashMap集合key部分的元素,以及放在HashSet集合中的元素,需要同时重写hashCode和equals方法
  • HashMap允许key和value为null,但key null值只能有一个
public class HashMapTest {
    public static void main(String[] args) {
        // Integer是key,它的hashCode和equals都重写了。
        Map<Integer,String> map = new HashMap<>();
        map.put(1, "zhangsan");
        map.put(6, "lisi");
        map.put(7, "wangwu");
        map.put(2, "zhaoliu");
        map.put(2, "king"); //key重复的时候value会自动覆盖。
        System.out.println(map.size()); // 4
        // 遍历Map集合
        Set<Map.Entry<Integer,String>> set = map.entrySet();
        for(Map.Entry<Integer,String> entry : set){
            // 验证结果:HashMap集合key部分元素:无序不可重复。
            System.out.println(entry.getKey() + "=" + entry.getValue());
        }
    }
}

HashTable

  • Hashtable和HashMap一样,底层都是哈希表数据结构
  • Hashtable的初始化容量是11,默认加载因子是:0.75f
  • Hashtable的扩容是:原容量 * 2 + 1
  • Hashtable的key和value都是不能为null的
Map map = new Hashtable();
map.put(null, "123");//NullPointerException
map.put(100, null);//NullPointerException

Properties

  • Properties是一个Map集合,继承Hashtable,Properties的key和value都是String类型
  • Properties是线程安全的
public class PropertiesTest {
    public static void main(String[] args) {
        // 创建一个Properties对象
        Properties pro = new Properties();
        // 需要掌握Properties的两个方法,一个存,一个取。
        pro.setProperty("url", "jdbc:mysql://localhost:3306/whydb");
        pro.setProperty("driver","com.mysql.jdbc.Driver");
        pro.setProperty("username", "root");
        pro.setProperty("password", "123");
        // 通过key获取value
        String url = pro.getProperty("url");
        String driver = pro.getProperty("driver");
        String username = pro.getProperty("username");
        String password = pro.getProperty("password");

        System.out.println(url);
        System.out.println(driver);
        System.out.println(username);
        System.out.println(password);
    }
}

TreeMap

TreeMap集合也是用来存储键值映射关系的,TreeMap不允许出现重复的键,该映射关系根据其键的自然顺序进行排序,或者根据创建映射时提供的Comparator进行排序。TreeMap的底层采用了二叉树这种数据结构

public class HashtableTest01 {
    public static void main(String[] args) {
	    Map<Integer,String > treeMap = new TreeMap<>();
        treeMap.put(1,"张三");
        treeMap.put(9,"李四");
        treeMap.put(8,"王五");
        treeMap.put(2,"赵六");
        Set<Map.Entry<Integer, String>> entries = treeMap.entrySet();
        for (Map.Entry<Integer, String> entry : entries) {
            System.out.println(entry.getKey()+"=="+entry.getValue());
        }
	}
}

【运行结果】

1==张三
2==赵六
8==王五
9==李四

Process finished with exit code 0

Collections工具类

Collections常用方法

返回类型方法名描述
static booleanaddAll(Collection<? super T>,T…elements)将所有指定元素添加到Collection中
static voidreserve(List<?> list)反转指定列表中的元素
static voidshuffle(List<?> list)使用默认随机源对指定列表进行置换
static voidsort(List<?> list)根据元素的自然顺序进行升序排序
static voidswap(List<?> list,int i,int j)将指定列表中i处元素和j处元素进行交换
static intbinarySearch(List<?> list,Object key)使用二分查找搜索指定列表
static Objectmax(Collection col)根据元素的自然顺序返回给定集合中的最大元素
static Objectmin(Collection col)根据元素的自然顺序返回给定集合中的最小元素
static booleanreplaceAll(List list,Object oldVal,Object newVal)使用newVal替换列表中所有的oldVal
static List<T>synchronizedList(List<T> list)将指定集合转换成线程安全

相关文章