[Java基础]3. Java集合

[Java基础]3. Java集合

Java集合类是一种特别有用的工具类,可用于存储数量不等的对象,并可以实现常用的数据结构,如栈、队列等。除此之外,Java集合还可用于保存具有映射关系的关联数组。Java集合大致可分为List、Set、Queue和Map四种体系,其中List代表有序、重复的集合;Set代表无序、不可重复的集合;而Map则代表具有映射关系的集合,Java5又增加了Queue体系集合,代表一种队列集合实现。

一、Java集合概述

为了保存数量不确定的数据,以及保存具有映射关系的数据(也被称为关联数组),Java提供了集合类。集合类主要负责保存、盛装其他数据,因此集合类也被称为容器类,所有的集合类都位于java.util包下。

集合类和数组不一样,数组元素既可以是基本类型的值,也可以是对象(实际上保存的是对象的引用变量);而集合里只能保存对象(实际上只是保存对象的引用变量,但通常习惯上认为集合里保存的是对象)。

Java的集合类主要由两个接口派生而出:CollectionMap, Collection和Map是Java集合框架的根接口,这两个接口又包含了一些子接口或实现类。如下所示是 Java集合简单结构图

在这里插入图片描述

二、List集合

java.util.List接口继承自Collection接口,在List集合元素可重复、元素有序。所有的元素是以一种线性方式进行存储的,在程序中可以通过索引来访问集合中的指定元素(从0开始),而且元素的存入顺序和取出顺序一致。

List作为Collection集合的子接口,不但继承了Collection接口中的全部方法,还有一些根据元素索引来操作集合的特有方法:

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

ArrayList集合
java.util.ArrayList集合数据存储的结构是数组结构。元素增删慢,查找快,由于日常开发中使用最多的功能为查询数据、遍历数据,所以ArrayList是最常用的集合。

LinkedList集合
java.util.LinkedList集合数据存储的结构是双向链表结构。元素增删快,查找慢的集合。

LinkedList提供了大量首尾操作的方法(了解即可):
public void addFirst(E e):将指定元素插入此列表的开头。
public void addLast(E e):将指定元素添加到此列表的结尾。
public E getFirst():返回此列表的第一个元素。
public E getLast():返回此列表的最后一个元素。
public E removeFirst():移除并返回此列表的第一个元素。
public E removeLast():移除并返回此列表的最后一个元素。
public E pop():从此列表所表示的堆栈处弹出一个元素。
public void push(E e):将元素推入此列表所表示的堆栈。
public boolean isEmpty():如果列表不包含元素,则返回true。

LinkedList是List的子类,List中的方法LinkedList都是可以使用,在开发时,LinkedList集合也可以作为堆栈,队列的结构使用。

public class LinkedListDemo {
    public static void main(String[] args) {
        LinkedList<String> link = new LinkedList<String>();
        //添加元素
        link.addFirst("a");
        link.addFirst("b");
        link.addFirst("c");
        System.out.println(link);
        // 获取元素
        System.out.println(link.getFirst());
        System.out.println(link.getLast());
        // 删除元素
        System.out.println(link.removeFirst());
        System.out.println(link.removeLast());
        while (!link.isEmpty()) { //判断集合是否为空
            System.out.println(link.pop()); //弹出集合中的栈顶元素
        }
        System.out.println(link);
    }
}

List方法返回值说明
add(E e)boolean向列表的尾部添加指定的元素。
add(int index, E element)void在列表的指定位置插入指定元素。
addAll(Collection c)boolean添加指定 collection 中的所有元素到此列表的结尾,顺序是指定 collection 的迭代器返回这些元素的顺序。
addAll(int index, Collection c)boolean将指定 collection 中的所有元素都插入到列表中的指定位置。
clear()void从列表中移除所有元素。
contains(Object o)boolean如果列表包含指定的元素,则返回 true。
containsAll(Collectionc)boolean如果列表包含指定 collection 的所有元素,则返回 true。
equals(Object o)boolean比较指定的对象与列表是否相等。
get(int index)E返回列表中指定位置的元素。
hashCode()int返回列表的哈希码值。
indexOf(Object o)int返回此列表中第一次出现的指定元素的索引;如果此列表不包含该元素,则返回-1。
isEmpty()boolean如果列表不包含元素,则返回 true。
iterator()Iterator返回按适当顺序在列表的元素上进行迭代的迭代器。
lastIndexOf(Object o)int返回此列表中最后出现的指定元素的索引;如果列表不包含此元素,则返回-1。
listIterator()ListIterator返回此列表元素的列表迭代器(按适当顺序)。
listIterator(int index)ListIterator返回列表中元素的列表迭代器(按适当顺序),从列表的指定位置开始。
remove(int index)E移除列表中指定位置的元素。
remove(Object o)boolean从此列表中移除第一次出现的指定元素(如果存在)。
removeAll(Collection c)boolean从列表中移除指定 collection 中包含的其所有元素。
retainAll(Collection c)boolean仅在列表中保留指定 collection 中所包含的元素。
set(int index, E element)E用指定元素替换列表中指定位置的元素。
size()int返回列表中的元素数。
subList(int fromIndex, int toIndex)List返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。
toArray()Object[]返回按适当顺序包含列表中的所有元素的数组(从第一个元素到最后一个元素)。
toArray(T[] a)T[]返回按适当顺序(从第一个元素到最后一个元素)包含列表中所有元素的数组;返回数组的运行时类型是指定数组的运行时类型。

示例代码(以ArrayList为例):

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ListDemo {
	public static void main(String[] args) {
		List<String> list = new ArrayList<>();
		// 添加元素
		list.add("A");
		list.add("B");
		list.add("C");
		list.add("D");
		list.add("E");
		list.add("A");//允许元素重复
		list.add("F");
		list.add("G");
		list.add(null);//允许元素为null
		list.add(null);
		// 移除
		list.remove(1);// 通过索引移除
		list.remove("D");// 通过对象移除
		List<String> listRemove = new ArrayList<>();
		listRemove.add("E");
		listRemove.add("F");
		list.removeAll(listRemove);// 移除多个
		// 输出list
		System.out.println(list);
		//遍历
		System.out.println("for循环遍历"); 
		for (int i = 0; i < list.size(); i++) {
			System.out.print(list.get(i) + "\t"); // 获取list中某个元素 list.get(index)
		}
		System.out.println("\nforeach 循环:");
		for (String string : list) {
			System.out.print(string + "\t");
		}
		// Iterator迭代器
		System.out.println("\nIterator 迭代器 while 遍历:");
		Iterator<String> iterator = list.iterator();
		while (iterator.hasNext()) { // iterator.hasNext()判断是否有下一个元素
			System.out.print(iterator.next() + "\t");// iterator.next()获取下一个元素
		}
		System.out.println("\nIterator 迭代器 for 遍历:");
		for (Iterator<String> iterator2 = list.iterator(); iterator2.hasNext();) {
			String string = iterator2.next();
			System.out.print(string + "\t");
			
		System.out.println("-------------------------");		
		System.out.println("A元素第一次出现的位置:" + list.indexOf("A")); 
		System.out.println("A元素最后一次出现的位置:" + list.lastIndexOf("A"));
		System.out.println("List集合中是否存在元素:" + list.contains("A"));
		// 替换元素
		list.set(1, "D");
		System.out.println(list);
		//返回列表中[fromIndex,toIndex)的部分视图
		List<String> sList = list.subList(1, 2);
		System.out.println(sList);
		System.out.println("List集合否为空:" + list.isEmpty());
		list.clear();// 清空集合
		System.out.println("List集合否为空:" + list.isEmpty());
	}
}
三、Set集合

java.util.Set接口继承自Collection接口,它与Collection接口中的方法基本一致,Set接口中元素无序且不重复,刚好全与list相反

如果试图把两个相同的元素加入同一个Set集合中,则添加操作失败,add()方法返回 false,且新元素不会被加入。

Set集合方法返回值说明
add(E e)boolean如果 set 中尚未存在指定的元素,则添加此元素。
addAll(Collection c)boolean如果 set 中没有指定 collection 中的所有元素,则将其添加到此 set 中。
clear()void移除此 set 中的所有元素。
contains(Object o)boolean如果 set 包含指定的元素,则返回 true。
containsAll(Collection c)boolean如果此 set 包含指定 collection 的所有元素,则返回 true。
equals(Object o)boolean比较指定对象与此 set 的相等性。
hashCode()int返回 set 的哈希码值。
isEmpty()boolean如果 set 不包含元素,则返回 true。
iterator()int返回在此 set 中的元素上进行迭代的迭代器。
remove(Object o)boolean如果 set 中存在指定的元素,则将其移除。
removeAll(Collection c)boolean移除 set 中那些包含在指定 collection 中的元素。
retainAll(Collection c)boolean仅保留 set 中那些包含在指定 collection 中的元素。
size()int返回 set 中的元素数(其容量)。
toArray()Object[]返回一个包含 set 中所有元素的数组。
toArray(T[] a)T[]返回一个包含此 set 中所有元素的数组;返回数组的运行时类型是指定数组的类型。

(一)HashSet类

java.util.HashSetSet接口的一个实现类,它所存储的元素是不可重复、无序(即存取顺序不一致)。java.util.HashSet底层的实现其实是一个java.util.HashMap支持。

HashSet类具有以下特点:

  • 不能保证元素的排列顺序,顺序可能与添加顺序不同,顺序也有可能发生变化。
  • HashSet不是同步的(不是线程安全的),如果多个线程同时访问一个HashSet,假设有两个或者两个以上线程同时修改了 HashSet集合时,则必须通过代码来保证其同步。
  • 集合元素值可以是null,但只能放入一个null。

HashSet是根据对象的哈希值来确定元素在集合中的存储位置,因此具有良好的存取和查找性能。保证元素唯一性的方式依赖于:hashCodeequals方法。

HashSet判断元素不相等的依据:对象的equals()比较返回false,且hashCode值不相等。

当向HashSet集合中存入一个元素时, HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据该hashCode值决定该对象在HashSet中的存储位置。如果有两个元素通过 equals方法比较返回true,但它们的hashCode()方法返回值不相等, HashSet将会把它们存储在不同的位置,依然可以添加成功。

给HashSet中存放自定义类型元素时,需要重写对象中的hashCode和equals方法,建立自己的比较方式,才能保证HashSet集合中的对象唯一。

public class Student {
    private String name;
    private int age;
    public Student() {
    }
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public boolean equals(Object o) {
        if (this == o)
            return true;
        if (o == null || getClass() != o.getClass())
            return false;
        Student student = (Student) o;
        return age == student.age &&
               Objects.equals(name, student.name);
    }
    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}

hashset示例

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

public class HashSetDemo {
	public static void main(String[] args) {
		HashSet<String> set = new HashSet<>();
		// 添加元素
		set.add("B");
		set.add("A");
		set.add("C");
		set.add("A");
		set.add("I");
		set.add("I");
		set.add(null);//可以放入null,但只能放入一个null
		// 移除
		//set.remove("I");
		List<String> list = new ArrayList<>();
		list.add("F");
		set.removeAll(list);

		// 输出set
		System.out.println(set.toString());
		// 遍历
		System.out.println("foreach遍历:");
		for (String string : set) {
			System.out.print(string + " ");
		}
		// 迭代器遍历
		System.out.println("\nIterator 迭代器 while:");
		Iterator<String> iterator = set.iterator();
		while (iterator.hasNext()) {
			System.out.print(iterator.next() + " ");
		}
		System.out.println("\nIterator 迭代器 for:");
		for (Iterator<String> iterator2 = set.iterator(); iterator2.hasNext();) {
			String string = (String) iterator2.next();
			System.out.print(string + " ");
		}
		// 获取元素个数
		System.out.println("HashSet的元素格个数:" + set.size());
		// HashSet中是否包含某个元素
		System.out.println("HashSet中是否包含某个元素:" + set.contains("F"));
		//清空set
		set.clear();
		//
		System.out.println("set是否为空"+set.isEmpty());
	}
}

(二)LinkedHashSet类

HashSet类还有一个子类 LinkedHashSet当遍历 LinkedhashSet集合里的元素时, LinkedHashSet将会按元素的添加顺序来访问集合里的元素。 LinkedHashSet需要维护元素的插入顺序,因此性能略低于 HashSet的性能,但在迭代访问Set里的全部元素时将有很好的性能,因为它以链表来维护内部顺序。

(三)TreeSet类

TreeSet是 SortedSet接口的实现类,正如 SortedSet名字所暗示的, TreeSet可以确保集合元素处于排序状态。与 Set集合相比,TreeSet还提供了如下几个额外的方法。

方法返回值说明
comparator()Comparator返回对此 set 中的元素进行排序的比较器;如果此 set使用其元素的自然顺序,则返回 null。
first()E返回此 set 中当前第一个(最低)元素。
floor(E e)E返回此 set 中小于等于给定元素的最大元素;如果不存在这样的元素,则返回 null。
higher(E e)E返回此 set 中严格大于给定元素的最小元素;如果不存在这样的元素,则返回 null。
last()E返回此 set 中当前最后一个(最高)元素。
lower(E e)E返回此 set 中严格小于给定元素的最大元素;如果不存在这样的元素,则返回 null。
ceiling(E e)E返回此 set 中大于等于给定元素的最小元素;如果不存在这样的元素,则返回 null。
headSet(E toElement)SortedSet返回此 set 的部分视图,其元素严格小于 toElement。
tailSet(E fromElement)SortedSet返回此 set 的部分视图,其元素大于等于fromElement。
subSet(E fromElement, E toElement)SortedSet返回此 set 的部分视图,其元素从 fromElement(包括)到 toElement(不包括)。

(四)、各Set实现类的选择

HashSet和TreeSet是Set的两个典型实现,如何选择HashSet和TreeSet?

HashSet的性能总是比TreeSet好(特别是最常用的添加、查询元素等操作),因为TreeSet需要额外的红黑树算法来维护集合元素的次序。只有当需要一个保持排序的Set时,才应该使用TreeSet,否则一般都应该使用HashSet

LinkedHashSet对于普通的插入、删除操作,LinkedHashSet比HashSet要略微慢一点,这是由维护链表所带来的额外开销造成的,但由于有了链表,遍历LinkedHashSet会更快。

Set的实现类HashSet、TreeSet都是线程不安全的。如果有多个线程同时访问一个Set集合,并且有超过一个线程修改了该Set集合,则必须手动保证该Set集合的同步性。通常可以通过Collections工具类的synchronizedSortedSet方法来“包装”该Set集合。

Set<String> set= Collections.synchronizedSet(new HashSet<String>());
四、Queue队列
方法返回值说明
add(E e)boolean将指定的元素插入此队列(如果立即可行且不会违反容量限制),在成功时返回 true,
如果当前没有可用的空间,则抛出IllegalStateException。
element()E获取,但是不移除此队列的头。
offer(E e)boolean将指定的元素插入此队列(如果立即可行且不会违反容量限制)
peek()E获取但不移除此队列的头;如果此队列为空,则返回 null。
poll()E获取并移除此队列的头,如果此队列为空,则返回 null。
remove()E获取并移除此队列的头。
import java.util.LinkedList;
import java.util.Queue;
public class QueueDemo {
	public static void main(String[] args) {
		// add()和remove()方法在失败的时候会抛出异常(不推荐)
		Queue<String> queue = new LinkedList<String>();
		// 添加元素
		queue.offer("同学A");
		queue.offer("同学B");
		queue.offer("同学C");
		// 遍历队列
		System.out.println("‐‐‐‐遍历队列‐‐‐‐");
		for (String q : queue) {
			System.out.print(q + "\t");
		}
		System.out.println();
		// 返回第一个元素,并在队列中删除
		System.out.println("‐‐‐‐‐‐poll‐‐‐‐‐‐");
		System.out.println("poll " + queue.poll());
		System.out.println(queue);
		// 返回第一个元素
		System.out.println("‐‐‐‐‐‐element‐‐‐‐‐‐");
		System.out.println("element " + queue.element());
		System.out.println(queue);
		// 返回第一个元素
		System.out.println("‐‐‐‐‐‐peek‐‐‐‐‐‐");
		System.out.println("peek " + queue.peek());
		System.out.println(queue);
	}
}
五、Map集合

Map接口中键和值一一映射. 可以通过键来获取值。

  • 给定一个键和一个值,你可以将该值存储在一个Map对象. 之后,你可以通过键来访问对应的值。
  • 当访问的值不存在的时候,方法就会抛出一个NoSuchElementException异常.
  • 当对象的类型和Map里元素类型不兼容的时候,就会抛出一个ClassCastException异常。
  • 当在不允许使用Null对象的Map中使用Null对象,会抛出一个NullPointerException 异常。
  • 当尝试修改一个只读的Map时,会抛出一个UnsupportedOperationException异常。
方法返回值说明
clear()void从此映射中移除所有映射关系(可选操作)。
containsKey(Object key)boolean如果此映射包含指定键的映射关系,则返回 true。
containsValue(Object value)boolean如果此映射将一个或多个键映射到指定值,则返回true。
entrySet()Set<Map.Entry>返回此映射中包含的映射关系的 Set 视图。
equals(Object o)boolean比较指定的对象与此映射是否相等。
get(Object key)V返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。
hashCode()int返回此映射的哈希码值。
isEmpty()boolean如果此映射未包含键-值映射关系,则返回 true。
keySet()Set返回此映射中包含的键的 Set 视图。
put(K key, V value)V将指定的值与此映射中的指定键关联
putAll(Map m)void从指定映射中将所有映射关系复制到此映射中
remove(Object key)V如果存在一个键的映射关系,则将其从此映射中移除
size()int返回此映射中的键值映射关系数。
values()Collection返回此映射中包含的值的 Collection 视图。
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class HashMapAndHashTable {
	public static void main(String[] args) {
		// 如果是基本数据类型,声明的map的时候使用包装类
		Map<Integer, String> map = new HashMap<>();
		// 添加数据 put当key不存在时,添加key‐value
		map.put(1, "str1");
		map.put(2, "str2");
		map.put(3, "str3");
		map.put(4, "str4");
		map.put(5, "str5");
		// put 当key存在时,修改key对应的value
		map.put(5, "111111");
		map.put(6, null);
		map.put(7, null);
		// 移除 remove(key)
		map.remove(7);
		// 判断是否存在key
		System.out.println("是否存在key:5===》" + map.containsKey(5));
		// 判断是否存在value
		System.out.println("是否存在Value:str4====>" + map.containsValue("str4"
		// 清空map
		// map.clear();
		System.out.println("map是否为空:" + map.isEmpty());
		// 输出
		System.out.println(map);
		
		// 遍历
		Set<Integer> keysSet = map.keySet();
		Iterator<Integer> iterator = keysSet.iterator();
		while (iterator.hasNext()) {
			Integer intKey = iterator.next();
			System.out.println("key:" + intKey + "‐‐‐‐>Value:" + map.get(intKey));
		}
		System.out.println("‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐");
		for (Iterator<Integer> iterator2 = keysSet.iterator(); iterator2.hasNext
			int intKey = iterator2.next();
			System.out.println("key:" + intKey + "‐‐‐‐>Value:" + map.get(intKey));
		}
		System.out.println("‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐");
		for (int intKey : keysSet) {
			System.out.println("key:" + intKey + "‐‐‐‐>Value:" + map.get(intKey));
		}
	}
}

TreeMap类

与 TreeSet类似的是,TreeMap中也提供了一系列根据key顺序访问key-value对的方法:

方法返回值说明
firstEntry()Map.Entry返回一个与此映射中的最小键关联的键值映射关系;
如果映射为空,则返回 null。
firstKey()K返回此映射中当前第一个(最低)键。
lastEntry()Map.Entry返回与此映射中的最大键关联的键值映射关系;
如果映射为空,则返回 null。
lastKey()K返回映射中当前最后一个(最高)键。
higherEntry(K key)Map.Entry返回一个键值映射关系,它与严格大于给定键的最小键关联;
如果不存在这样的键,则返回 null。
higherKey(K key)K返回严格大于给定键的最小键;如果不存在这样的键,则返回 null。
lowerEntry(K key)Map.Entry返回一个键值映射关系,它与严格小于给定键的最大键关联;
如果不存在这样的键,则返回 null。
lowerKey(K key)K返回严格小于给定键的最大键;
如果不存在这样的键,则返回 null。
headMap(K toKey)SortedMap返回此映射的部分视图,其键值严格小于 toKey。
subMap(K fromKey, K toKey)SortedMap返回此映射的部分视图,其键值的范围[ fromKey , toKey )
tailMap(K fromKey)SortedMap返回此映射的部分视图,其键大于等于 fromKey。
六、Java集合工具类:Collections

Java提供了一个操作Set、List和Map等集合的工具类:Collections,该工具类里提供了大量方法对集合元素进行排序、查询和修改等操作,还提供了对集合对象实现同步控制等方法。

public static <T> boolean addAll(Collection<T> c, T... elements): 往集合中添加一些元素。
public static void shuffle(List<?> list) 打乱顺序:打乱集合顺序。
public static void sort(List list):将集合中元素按照默认规则排序。
public static void sort(List list,Comparator<? super T> ):将集合中元素按照指定规则排序。

(一)排序操作

方法修饰符返回值说明
reverse(List list)staticvoid反转指定列表中元素的顺序。
shuffle(List list)staticvoid打乱集合顺序
sort(List list)staticvoid将集合中元素按照默认规则排序
sort(List list, Comparator c)staticvoid将集合中元素按照指定规则排序
swap(List list, int i, int j)staticvoid在指定列表的指定位置处交换元素。
rotate(List list, int distance)staticvoid根据指定的距离轮换指定列表中的元素。
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class SortDemo {
	public static void main(String[] args) {
		List<Integer> list = new ArrayList<>();
		原来添加写法
		//list.add(1);
		//list.add(2);
		//list.add(3);
		//list.add(4);
		//list.add(5);
		//list.add(6);
		//list.add(7);
		//list.add(8);
		//list.add(9);
		//采用工具类 完成 往集合中添加元素
		Collections.addAll(list, 1, 2, 34, 5, 6, 7, 8, 9);
		System.out.println("list‐‐>"+list);
		System.out.println("‐‐‐‐倒序 reverse‐‐‐");
		Collections.reverse(list);//倒序 9,8,7,6,5,4,3,2,1,
		System.out.println("list‐‐>"+list);
		System.out.println("‐‐‐随机顺序 shuffle‐‐‐");
		Collections.shuffle(list);//每次执行后的顺序都是随机排列的
		System.out.println("list‐‐>"+list);
		System.out.println("‐‐‐自然顺序排序 sort‐‐‐");
		Collections.sort(list);//自然顺序排序
		System.out.println("list‐‐>"+list);
		System.out.println("‐‐‐自定义排序 sort‐‐‐");
		Collections.sort(list,new Comparator<Integer>() {
			@Override
			public int compare(Integer o1, Integer o2) {
				//从大到小
				return o2‐o1;
			}
		});
		System.out.println("list‐‐>"+list);
		System.out.println("‐‐‐交换元素 swap‐‐‐");
		Collections.swap(list,0,8); 
		System.out.println("list‐‐>"+list);
		System.out.println("‐‐‐自然顺序排序 sort‐‐‐");
		Collections.sort(list); //自然顺序排序
		System.out.println("list‐‐>"+list);
		System.out.println("‐‐‐rotate(2)‐‐‐");
		Collections.rotate(list,2);
		System.out.println("list‐‐>"+list);
		System.out.println("‐‐‐rotate(‐2)‐‐‐");
		Collections.rotate(list,2);
		System.out.println("list‐‐>"+list);
	}
}

(二)查找和替换操作

下列方法的修饰符都是static

方法返回值说明
binarySearch(List list, T key)int使用二分搜索法搜索指定列表,以获得指定对象。
binarySearch(List list, T key,Comparator c)int使用二分搜索法搜索指定列表,以获得指定对象。
max(Collection coll)Object根据元素的自然顺序,返回给定 collection 的最大元素。
max(Collection coll,Comparator c)Object根据指定比较器产生的顺序,返回给定collection 的最大元素。
min(Collection coll)Object根据元素的自然顺序,返回给定 collection 的最小元素。
min(Collection coll,Comparator c)Object根据指定比较器产生的顺序,返回给定collection 的最小元素。
fill(List list, T obj)void使用指定元素替换指定列表中的所有元素。
frequency(Collection c, Object o)int返回指定 collection 中等于指定对象的元素数。
indexOfSubList(List source, List target)int返回指定源列表中第一次出现指定目标列表的起始位置;
如果没有出现这样的列表,则返回-1。
lastIndexOfSubList(List source, List target)int返回指定源列表中最后一次出现指定目标列表的起始位置;
如果没有出现这样的列表,则返回-1。
replaceAll(List list, T oldVal, T newVal)boolean使用另一个值替换列表中出现的所有某一指定值。
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class SearchDemo {
public static void main(String[] args)
	{
		List<Integer> list = new ArrayList<>();
		list.add(5);
		list.add(10);
		list.add(3);
		list.add(9);
		list.add(1);
		list.add(7);
		list.add(0);
		System.out.println(list);
		System.out.println("‐‐‐‐‐max‐‐‐‐");
		System.out.println(Collections.max(list)); // 输出最大元素
		System.out.println("‐‐‐‐‐min‐‐‐‐");
		System.out.println(Collections.min(list)); // 输出最小元素
		System.out.println("‐‐‐‐‐replaceAll‐‐‐‐");
		Collections.replaceAll(list , 0 , 1); // 将nums中的0使用1来代替
		System.out.println(list);
		System.out.println("‐‐‐‐‐frequency‐‐‐‐"); 
		System.out.println(Collections.frequency(list , 5)); // 判断5在List集合中出现的次数
		System.out.println("‐‐‐‐‐binarySearch‐‐‐‐");
		Collections.sort(list); // 对nums集合排序
		System.out.println(list);
		//只有排序后的List集合才可用二分法查询元素的索引
		System.out.println(Collections.binarySearch(list , 5));
		List<Integer> list2 = new ArrayList<>();
		list2.add(1);
		list2.add(1);
		System.out.println("‐‐‐‐‐indexOfSubList‐‐‐‐");
		System.out.println(Collections.indexOfSubList(list, list2));//查找子列表
		System.out.println("‐‐‐-‐lastIndexOfSubList‐‐‐‐");
		System.out.println(Collections.lastIndexOfSubList(list , list2));//查找子列表
		System.out.println("‐‐‐‐‐fill‐‐‐‐");
		Collections.fill(list, 0);//用0填充list
		System.out.println(list);
	}
}

(三)同步控制

Collections类中提供了多个 synchronized…()方法,这些方法可以将指定集合包装成线程同步(线程安全)的集合,从而可以解决多线程并发访问集合时的线程安全问题。

Java中常用的集合框架中的实现类 ArrayList、Linkedlist、 HashSet、TreeSet、HashMap和TreeMap都是线程不安全的。如果有多个线程访问它们,而且有超过一个的线程试图修改它们,则存在线程安全的问题。 Collections提供了多个类方法可以把它们包装成线程同步的集合。

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class SynchronizedDemo {
	public static void main(String[] args) {
		List<String> list=Collections.synchronizedList(new ArrayList<String>());
		Set<String> set=Collections.synchronizedSet(new HashSet<String>());
		Map<Integer, String> map=Collections.synchronizedMap(new HashMap<Integer>());
	}
}
七、Comparable和Comparator

(一)Comparable

Comparable是排序接口。若一个类实现了Comparable接口,就意味着该类支持排序。实现了Comparable接口的类的对象的列表或数组可以通过Collections.sortArrays.sort进行自动排序,无需指定比较器。
Comparable接口只有一个方法compare,比较此对象与指定对象的顺序,如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。

示例

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

//Comparable 排序接口 是在类的内部实现
public class ListComparable {
	public static void main(String[] args) {
		List<PersonComparable> persons = new ArrayList<PersonComparable>();
		persons.add(new PersonComparable("小A", 35));
		persons.add(new PersonComparable("小B", 25));
		persons.add(new PersonComparable("小C", 25));
		persons.add(new PersonComparable("小D", 12));
		persons.add(new PersonComparable("小X", 33));
		persons.add(new PersonComparable("小M", 33));
		persons.add(new PersonComparable("小E", 33));
		//第三步 调用sort 排序
		Collections.sort(persons);
		//使用迭代器遍历输出列表数据
		Iterator<PersonComparable> iterator = persons.iterator();
		while (iterator.hasNext()) {
		PersonComparable persion = iterator.next();
		System.out.println(persion.getName()+"\t"+persion.getAge());
		}
	}
}

// 第一步 :实现接口Comparable<T>
class PersonComparable implements Comparable<PersonComparable> {
	private int age;
	private String name;
	public PersonComparable() {
	}
	public PersonComparable(String name, int age) {
		this.name = name;
		this.age = age;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}

	/**
	* 第二步 实现compareTo方法,o表示和当前对象比较的另外一个对象
	*/
	@Override
	public int compareTo(PersonComparable o) {
		// 从小到大 :this‐o
		// 从大到小:o‐this
		// return this.age ‐ o.age;
		//改进比较方法:先根据年龄排序,如果年龄一样,根据姓名排序
		if (this.age!=o.age) {
			return this.age ‐ o.age;
		} else {
			return this.name.compareTo(o.name);
		}
	}
}

(二)Comparator

Comparator是比较接口,我们如果需要控制某个类的次序,而该类本身不支持排序(即没有实现Comparable接口),那么我们就可以建立一个“该类的比较器”来进行排序,这个“比较器”只需要实现Comparator接口即可。也就是说,我们可以通过实现
Comparator来新建一个比较器,然后通过这个比较器对类进行排序。

注意:

  • 若一个类要实现Comparator接口:它一定要实现compare(T o1, T o2)函数,但可以不实现equals(Object obj)函数。
  • int compare(T o1, T o2)是“比较o1和o2的大小”。返回“负数”,意味着“o1比o2小”;返回“零”,意味着“o1等于o2”;返回“正数”,意味着“o1大于o2”。
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
public class ListComparator {
	public static void main(String[] args) {
		List<PersonComparator> persons = new ArrayList<PersonComparator>();
		persons.add(new PersonComparator("小A", 35));
		persons.add(new PersonComparator("小B", 25));
		persons.add(new PersonComparator("小C", 25));
		persons.add(new PersonComparator("小D", 12));
		persons.add(new PersonComparator("小X", 33));
		persons.add(new PersonComparator("小M", 33));
		persons.add(new PersonComparator("小E", 33));
		// 调用sort 排序
		Collections.sort(persons, new Comparator<PersonComparator>() {
			@Override
			public int compare(PersonComparator o1, PersonComparator o2) {
				/**
				* 从小到大:o1‐o2 从大到小:o2‐o1
				*/
				//改进比较方法:先根据年龄排序,如果年龄一样,根据姓名排序
				if (o1.getAge() != o2.getAge()) {
					return o1.getAge() ‐ o2.getAge();
				} else {
					return o2.getName().compareTo(o1.getName());
				}
			}
		});
		//使用迭代器遍历输出列表数据
		Iterator<PersonComparator> iterator = persons.iterator();
		while (iterator.hasNext()) {
			PersonComparator persion = iterator.next();
			System.out.println(persion.getName()+"\t"+persion.getAge());
		}
	}
}
class PersonComparable implements Comparable<PersonComparable> {
	private int age;
	private String name;
	public PersonComparable() {
	}
	public PersonComparable(String name, int age) {
		this.name = name;
		this.age = age;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}

(三)Comparable和Comparator区别比较

  1. Comparable是排序接口,若一个类实现了Comparable接口,就意味着“该类支持排序”。Comparator是比较器,我们若需要控制某个类的次序,可以建立一个“该类的比较器”来进行排序。
  2. 用Comparable简单, 只要实现Comparable 接口的对象直接就成为一个可以比较的对象,但是需要修改源代码。 用Comparator 的好处是不需要修改源代码, 而是另外实现一个比较器, 当某个自定义的对象需要作比较的时候,把比较器和对象一起传递过去就可以比大小了, 并且在Comparator里面用户可以自己实现复杂的可以通用的逻辑,使其可以匹配一些比较简单的对象,那样就可以节省很多重复劳动了。
八、Java集合总结
  • List,Set,Map是集合体系中最主要的三个接口。其中list和set是继承自collection接口,Map也属于集合系统但是与collection接口不同。
  • list是有序且允许元素重复,允许元素为null,ArrayList、LinkedList和Vector是三个主要的实现类
    • Vector、ArrayList都是以类似数组的形式存储在内存中,LinkedList则以链表的形式进行存储。
    • Vector线程安全的(同步),ArrayList、LinkedList线程不安全的(不同步)。
    • ArrayList、Vector适合查找,不适合指定位置的插入、删除操作;LinkedList适合指定位置插入、删除操作,不适合查找。
    • ArrayList在元素填满容器时会自动扩充容器大小的50%,而Vector则是100%,因此ArrayList更节省空间。
  • set是无序,不允许元素重复;HashSet和TreeSet是两个实现类
    • HashSet 基于HashMap实现,HashSet中的数据是无序的,可以放入null,但只能放入一个null,两者中的值都不能重复,要求放入的对象必须实现HashCode()方法,放入的对象,是以hashcode码作为标识的
    • TreeSet 是二差树实现的,Treeset中的数据是自动排好序的,不允许放入null值
  • Comparator 和 Comparable 的区别
    • Comparator定义在类的外部, 此时我们的类的结构不需要有任何变化,从小到大:o1-o2从大到小:o2-o1
    • Comparable定义在类的内部,耦合性较强 从小到大 :this-o 从大到小:o-this
  • 线程安全的就是同步的,不安全的就是不同步的;不同步的运行速度要比同步的快。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值