1 java集合框架
1.1 Java集合框架的概述
- 一方面,面向对象语言对事物的体现都是以对象的形式,为了方便对多个对象的操作,就要对对象进行存储。另一方面,使用数组存储对象具有一些弊端,而Java集合就像容器一样,可以动态的把多个对象的引用放入到容器中。
- 数组在内存存储方面的特点:
- ①数组初始化以后,长度就确定了。
- ②数组声明的类型,就决定了进行元素初始化时的类型。
- 数组在存储数据方面的弊端:
- ①数组初始化以后,长度就不变了,不便于扩展。
- ②数组中提供的属性和方法少,不便于进行添加、删除、插入等操作,且效率不高。
- ③数组存储的数据是有序的、可以重复的。
- Java集合可以用于存储数量不等的多个对象,还可用于保存具有映射关系的关联数组。
1.2 Java集合的分类
- Java集合可以分为Collection和Map体系。
- Collection接口:单列数据,定义了存取一组对象的方法的集合。其中,List是元素有序、可以重复的集合。Set是元素无序、不可重复的集合。
- Map接口:双列数组,保存具有映射关系的“key-value”键值对。
1.3 集合框架的继承树
2 Collection接口中的常用方法
- 增加一个元素到集合中。
boolean add(E e);
- 示例:
package day18; import java.util.ArrayList; import java.util.Collection; public class CollectionTest { public static void main(String[] args) { Collection<String> collection = new ArrayList<>(); collection.add("张三"); System.out.println(collection); } }
- 增加一组元素(集合元素)到集合中。
boolean addAll(Collection<? extends E> c);
- 示例:
package day18; import java.util.ArrayList; import java.util.Collection; public class CollectionTest { public static void main(String[] args) { Collection<String> collection = new ArrayList<>(); Collection<String> collection1 = new ArrayList<>(); collection1.add("张三"); collection1.add("李四"); collection.addAll(collection1); System.out.println(collection); } }
- 获取集合中有效元素的个数。
int size();
- 示例:
package day18; import java.util.ArrayList; import java.util.Collection; public class CollectionTest { public static void main(String[] args) { Collection<String> collection = new ArrayList<>(); collection.add("张三"); collection.add("李四"); System.out.println("集合中元素的个数:" + collection.size()); } }
- 判断元素是否是空集合(元素的个数为0)。
boolean isEmpty();
- 示例:
package day18; import java.util.ArrayList; import java.util.Collection; public class CollectionTest { public static void main(String[] args) { Collection<String> collection = new ArrayList<>(); collection.add(null); System.out.println(collection.isEmpty());//false } }
- 判断集合是否包含某个指定元素:调用元素的equals()和hashCode()方法判断的。
boolean contains(Object o);
- 示例:
package day18; import java.util.ArrayList; import java.util.Collection; public class CollectionTest { public static void main(String[] args) { Collection<String> collection = new ArrayList<>(); collection.add("张三"); collection.add("李四"); System.out.println("判断是否包含某个元素:" + collection.contains("张三"));//true } }
- 判断集合中是否包含另一个集合中的所有元素:调用元素的equals()和hashCode()方法来判断的。此方法会拿集合中的元素依次比较
boolean containsAll(Collection<?> c);
- 示例:
package day18; import java.util.ArrayList; import java.util.Collection; public class CollectionTest { public static void main(String[] args) { Collection<String> collection = new ArrayList<>(); collection.add("张三"); collection.add("李四"); Collection<String> collection1 = new ArrayList<>(); collection1.add("张三"); System.out.println("判断一个集合中是否包含另一个集合中的所有元素" + collection.containsAll(collection1));//true } }
- 清空集合中的所有元素
void clear();
- 示例:
package day18; import java.util.ArrayList; import java.util.Collection; public class CollectionTest { public static void main(String[] args) { Collection<String> collection = new ArrayList<>(); collection.add("张三"); collection.add("李四"); collection.clear(); System.out.println("集合中的元素个数:" + collection.size()); } }
- 从集合中删除某个元素:会调用元素的equals()方法和hashCode()方法。
boolean remove(Object o);
- 示例:
package day18; import java.util.ArrayList; import java.util.Collection; public class CollectionTest { public static void main(String[] args) { Collection<String> collection = new ArrayList<>(); collection.add("张三"); collection.add("李四"); boolean flag = collection.remove("王五"); System.out.println("删除元素是否成功:"+flag);//flase flag = collection.remove("张三"); System.out.println("删除元素是否成功:"+flag);//true } }
- 从当前集合中删除指定集合在此集中中的所有元素:即求差集
boolean removeAll(Collection<?> c)
- 示例:
package day18; import java.util.ArrayList; import java.util.Collection; public class CollectionTest { public static void main(String[] args) { Collection<String> collection = new ArrayList<>(); collection.add("张三"); collection.add("李四"); collection.add("王五"); Collection<String> collection1 = new ArrayList<>(); collection1.add("王五"); collection1.add("赵六"); boolean flag = collection.removeAll(collection1); System.out.println("collection:" + collection);//[张三, 李四] System.out.println("从集合中删除指定集中的元素是否成功:" + flag);//true } }
- 把交集的结果存在当前集合之中
boolean retainAll(Collection<?> c);
- 示例:
package day18; import java.util.ArrayList; import java.util.Collection; public class CollectionTest { public static void main(String[] args) { Collection<String> collection = new ArrayList<>(); collection.add("张三"); collection.add("李四"); collection.add("王五"); Collection<String> collection1 = new ArrayList<>(); collection1.add("王五"); collection1.add("赵六"); boolean flag = collection.retainAll(collection1); System.out.println("collection:" + collection);//[王五] System.out.println("求交集是否成功:" + flag);//true } }
- 集合是否相等:调用集合中元素的eqauls()方法和hashCode()方法
boolean equals(Object o);
- 示例:
package day18; import java.util.ArrayList; import java.util.Collection; public class CollectionTest { public static void main(String[] args) { Collection<String> collection = new ArrayList<>(); collection.add("张三"); collection.add("李四"); collection.add("王五"); Collection<String> collection1 = new ArrayList<>(); collection1.add("张三"); collection1.add("李四"); collection1.add("王五"); System.out.println("collection1和Collection是否相等:" + collection.equals(collection1));//true } }
- 将集合转换为对象数组
Object[] toArray();
- 示例:
package day18; import java.util.ArrayList; import java.util.Collection; public class CollectionTest { public static void main(String[] args) { Collection<String> collection = new ArrayList<>(); collection.add("张三"); collection.add("李四"); collection.add("王五"); Object[] array = collection.toArray(); for (int i = 0; i < array.length; i++) { System.out.println(array[i]); } } }
- 获取集合对象的哈希值
int hashCode();
- 示例:
package day18; import java.util.ArrayList; import java.util.Collection; public class CollectionTest { public static void main(String[] args) { Collection<String> collection = new ArrayList<>(); collection.add("张三"); collection.add("李四"); collection.add("王五"); System.out.println("集合对象的哈希值:" + collection.hashCode()); } }
- 集合对象的遍历:使用迭代器
Iterator<E> iterator();
- 示例:
package day18; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class CollectionTest { public static void main(String[] args) { Collection<String> collection = new ArrayList<>(); collection.add("张三"); collection.add("李四"); collection.add("王五"); Iterator<String> iterator = collection.iterator(); while (iterator.hasNext()) { System.out.println("集合中的元素是:" + iterator.next()); } } }
3 JDK5新特性之foreach循环
3.1 说明
- JDK5提供了foreach循环迭代访问Collection和数组。
- 遍历操作不需要获取Collection或数组的长度,无需使用索引访问元素。
- 遍历集合的底层使用Iterator完成操作。
- foreach还可以用来遍历数组。
3.2 语法
for(数据类型 元素名称: 集合名称或数组名){ }
3.3 应用示例
- 示例:
package day18; import java.util.ArrayList; import java.util.Collection; public class CollectionTest { public static void main(String[] args) { Collection<String> collection = new ArrayList<>(); collection.add("张三"); collection.add("李四"); collection.add("王五"); for (String s : collection) { System.out.println("集合中的元素是:" + s); } } }
- 示例:
package day18; public class CollectionTest { public static void main(String[] args) { Integer[] integers = new Integer[]{1, 2, 3}; for (Integer integer : integers) { System.out.println("数组中的元素是:" + integer); } } }
4 Collection子接口之一List接口
4.1 List接口概述
- 鉴于Java中数组是用来存储数据的局限性,我们通常使用List替代数组。
- List集合类中元素有序、且可重复,集合中的每个元素都有其对应的顺序索引。
- List容器中的元素都对应一个整数型的序号记载其在容器中的位置,可以根据序号存取容器中的元素。
- JDK API中List接口的常用实现类通常有:ArrayList、LinkedList和Vector。
4.2 List接口方法
- List除了从Collection接口中继承的方法外,List集合还添加了一些根据索引来操作集合元素的方法。
- 在指定索引的位置插入数据。
void add(int index, E element);
- 示例:
package day18; import java.util.ArrayList; import java.util.List; /** * @motto: 一身转战三千里,一剑可当百万兵。 * @author: 不为往事扰,余生只爱笑。 * @version: 1.0 * @since: 2019-06-18 */ public class CollectionTest { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("11"); list.add("22"); list.add("33"); list.add("44"); list.add("55"); list.add(1,"aa"); System.out.println("集合中的元素是:" + list); } }
- 从指定的索引位置将另一个集合中的所有元素添加到本集合中。
boolean addAll(int index, Collection<? extends E> c);
- 示例:
package day18; import java.util.ArrayList; import java.util.List; /** * @motto: 一身转战三千里,一剑可当百万兵。 * @author: 不为往事扰,余生只爱笑。 * @version: 1.0 * @since: 2019-06-18 */ public class CollectionTest { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("11"); list.add("22"); list.add("33"); list.add("44"); list.add("55"); List<String> list1 = new ArrayList<>(); list1.add("aaa"); list1.add("bbb"); list1.add("ccc"); list.addAll(1,list1); System.out.println("集合中的元素是:" + list); } }
- 获取指定索引位置上的元素。
E get(int index);
- 示例:
package day18; import java.util.ArrayList; import java.util.List; /** * @motto: 一身转战三千里,一剑可当百万兵。 * @author: 不为往事扰,余生只爱笑。 * @version: 1.0 * @since: 2019-06-18 */ public class CollectionTest { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("11"); list.add("22"); list.add("33"); list.add("44"); list.add("55"); System.out.println("获取指定索引位置上的元素:" + list.get(2)); } }
- 返回元素在集合中首次出现的位置。
int indexOf(Object o);
- 示例:
package day18; import java.util.ArrayList; import java.util.List; /** * @motto: 一身转战三千里,一剑可当百万兵。 * @author: 不为往事扰,余生只爱笑。 * @version: 1.0 * @since: 2019-06-18 */ public class CollectionTest { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("11"); list.add("22"); list.add("33"); list.add("44"); list.add("55"); int index = list.indexOf("11"); System.out.println("获取元素在集合中首次出现的位置:" + index); } }
- 返回元素在集合中最后出现的位置。
int lastIndexOf(Object o);
- 示例:
package day18; import java.util.ArrayList; import java.util.List; /** * @motto: 一身转战三千里,一剑可当百万兵。 * @author: 不为往事扰,余生只爱笑。 * @version: 1.0 * @since: 2019-06-18 */ public class CollectionTest { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("11"); list.add("22"); list.add("33"); list.add("44"); list.add("55"); int index = list.lastIndexOf("44"); System.out.println("获取元素在集合中首次出现的位置:" + index); } }
- 从指定索引位置移除元素,并返回此元素。
E remove(int index);
- 示例:
package day18; import java.util.ArrayList; import java.util.List; /** * @motto: 一身转战三千里,一剑可当百万兵。 * @author: 不为往事扰,余生只爱笑。 * @version: 1.0 * @since: 2019-06-18 */ public class CollectionTest { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("11"); list.add("22"); list.add("33"); list.add("44"); list.add("55"); String ele = list.remove(1); System.out.println("从指定索引位置移除元素,并返回此元素:" + ele); } }
- 在集合中指定的位置,设置新元素,并返回旧元素。
E set(int index, E element);
- 示例:
package day18; import java.util.ArrayList; import java.util.List; /** * @motto: 一身转战三千里,一剑可当百万兵。 * @author: 不为往事扰,余生只爱笑。 * @version: 1.0 * @since: 2019-06-18 */ public class CollectionTest { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("11"); list.add("22"); list.add("33"); list.add("44"); list.add("55"); String oldEle = list.set(3, "aa"); System.out.println("在集合中指定位置设置新元素,并返回旧元素:" + oldEle); } }
- 返回指定范围的集合。
List<E> subList(int fromIndex, int toIndex);
- 示例:
package day18; import java.util.ArrayList; import java.util.List; /** * @motto: 一身转战三千里,一剑可当百万兵。 * @author: 不为往事扰,余生只爱笑。 * @version: 1.0 * @since: 2019-06-18 */ public class CollectionTest { public static void main(String[] args) { List<String> list = new ArrayList<>(); list.add("11"); list.add("22"); list.add("33"); list.add("44"); list.add("55"); List<String> stringList = list.subList(2, 4); System.out.println("返回指定范围内的集合:" + stringList); } }
4.3 List接口的实现类之ArrayList
- ArrayList是List接口中的典型实现类、主要实现类。
- 本质上,ArrayList是对象引用的一个“变长”数组。
- ArrayList在JDK1.8前后的实现区别:
- JDK1.7:ArrayList像饿汉式,直接创建一个初始容量为10的数组。
- JDK1.8:ArrayList像懒汉式,一开始创建一个长度为0的数组,当添加第一个元素的时候再创建一个容量为10的数组。
- 注意:Arrays.asList(...)方法返回的List集合,既不是ArrayList实例,也不是Vector实例。Arrays.asList(...)返回的是一个固定长度的List集合,所以当然不能新增和删除元素了。
4.4 List接口的实现类之LinkedList
- 对于频繁的插入或删除元素的操作,建议使用LinkedList。
- 在集合开头插入元素。
public void addFirst(E e) { linkFirst(e); }
- 示例:
package day18; import java.util.LinkedList; /** * @motto: 一身转战三千里,一剑可当百万兵。 * @author: 不为往事扰,余生只爱笑。 * @version: 1.0 * @since: 2019-06-18 */ public class CollectionTest { public static void main(String[] args) { LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("aa"); linkedList.add("bb"); linkedList.add("cc"); linkedList.add("dd"); linkedList.add("ee"); linkedList.addFirst("11"); System.out.println("集合中的元素是:" + linkedList); } }
- 在集合的结尾插入元素。
public void addLast(E e) { linkLast(e); }
- 示例:
package day18; import java.util.LinkedList; /** * @motto: 一身转战三千里,一剑可当百万兵。 * @author: 不为往事扰,余生只爱笑。 * @version: 1.0 * @since: 2019-06-18 */ public class CollectionTest { public static void main(String[] args) { LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("aa"); linkedList.add("bb"); linkedList.add("cc"); linkedList.add("dd"); linkedList.add("ee"); linkedList.addLast("11"); System.out.println("集合中的元素是:" + linkedList); } }
- 获取集合中开头元素。
public E getFirst() { final Node<E> f = first; if (f == null) throw new NoSuchElementException(); return f.item; }
- 示例:
package day18; import java.util.LinkedList; /** * @motto: 一身转战三千里,一剑可当百万兵。 * @author: 不为往事扰,余生只爱笑。 * @version: 1.0 * @since: 2019-06-18 */ public class CollectionTest { public static void main(String[] args) { LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("aa"); linkedList.add("bb"); linkedList.add("cc"); linkedList.add("dd"); linkedList.add("ee"); String first = linkedList.getFirst(); System.out.println("集合开头的元素是:" + first); } }
- 获取集合中的最后元素。
public E getLast() { final Node<E> l = last; if (l == null) throw new NoSuchElementException(); return l.item; }
- 示例:
package day18; import java.util.LinkedList; /** * @motto: 一身转战三千里,一剑可当百万兵。 * @author: 不为往事扰,余生只爱笑。 * @version: 1.0 * @since: 2019-06-18 */ public class CollectionTest { public static void main(String[] args) { LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("aa"); linkedList.add("bb"); linkedList.add("cc"); linkedList.add("dd"); linkedList.add("ee"); String last = linkedList.getLast(); System.out.println("集合结尾的元素是:" + last); } }
- 删除集合中的开头元素,并返回被删除的元素
public E removeFirst() { final Node<E> f = first; if (f == null) throw new NoSuchElementException(); return unlinkFirst(f); }
- 示例:
package day18; import java.util.LinkedList; /** * @motto: 一身转战三千里,一剑可当百万兵。 * @author: 不为往事扰,余生只爱笑。 * @version: 1.0 * @since: 2019-06-18 */ public class CollectionTest { public static void main(String[] args) { LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("aa"); linkedList.add("bb"); linkedList.add("cc"); linkedList.add("dd"); linkedList.add("ee"); String removeFirst = linkedList.removeFirst(); System.out.println("删除的元素是:" + removeFirst); System.out.println("集合的元素是:" + linkedList); } }
- 删除集合中的结尾元素,并返回被删除的元素。
public E removeLast() { final Node<E> l = last; if (l == null) throw new NoSuchElementException(); return unlinkLast(l); }
- 示例:
package day18; import java.util.LinkedList; /** * @motto: 一身转战三千里,一剑可当百万兵。 * @author: 不为往事扰,余生只爱笑。 * @version: 1.0 * @since: 2019-06-18 */ public class CollectionTest { public static void main(String[] args) { LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("aa"); linkedList.add("bb"); linkedList.add("cc"); linkedList.add("dd"); linkedList.add("ee"); String removeLast = linkedList.removeLast(); System.out.println("被删除的元素是:" + removeLast); System.out.println("集合中的元素是:" + linkedList); } }
4.5 List接口的实现类之Vector
- Vector是一个古老的集合,在JDK1.0就有了。大多数操作和ArrayList相同,区别在于Vector是线程安全的。
- 在各种List的子类中,最好把ArrayList作为缺省选择。当插入、删除频繁的时候,选择LinkedList。Vector总是比ArrayList慢,所以尽量避免使用。
- 增加元素。
public synchronized void addElement(E obj) { modCount++; ensureCapacityHelper(elementCount + 1); elementData[elementCount++] = obj; }
- 示例:
package day18; import java.util.Vector; /** * @motto: 一身转战三千里,一剑可当百万兵。 * @author: 不为往事扰,余生只爱笑。 * @version: 1.0 * @since: 2019-06-18 */ public class CollectionTest { public static void main(String[] args) { Vector<String> vector = new Vector<>(); vector.addElement("aaa"); vector.addElement("bbb"); vector.addElement("ccc"); System.out.println("vector集合中的元素:" + vector); } }
- 在指定位置插入元素。
public synchronized void insertElementAt(E obj, int index) { modCount++; if (index > elementCount) { throw new ArrayIndexOutOfBoundsException(index + " > " + elementCount); } ensureCapacityHelper(elementCount + 1); System.arraycopy(elementData, index, elementData, index + 1, elementCount - index); elementData[index] = obj; elementCount++; }
- 示例:
package day18; import java.util.Vector; /** * @motto: 一身转战三千里,一剑可当百万兵。 * @author: 不为往事扰,余生只爱笑。 * @version: 1.0 * @since: 2019-06-18 */ public class CollectionTest { public static void main(String[] args) { Vector<String> vector = new Vector<>(); vector.addElement("aaa"); vector.addElement("bbb"); vector.addElement("ccc"); vector.insertElementAt("qq",1); System.out.println("vector集合中的元素:" + vector); } }
- 在指定位置设置元素。
public synchronized void setElementAt(E obj, int index) { if (index >= elementCount) { throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount); } elementData[index] = obj; }
- 示例:
package day18; import java.util.Vector; /** * @motto: 一身转战三千里,一剑可当百万兵。 * @author: 不为往事扰,余生只爱笑。 * @version: 1.0 * @since: 2019-06-18 */ public class CollectionTest { public static void main(String[] args) { Vector<String> vector = new Vector<>(); vector.addElement("aaa"); vector.addElement("bbb"); vector.addElement("ccc"); vector.setElementAt("qq",1); System.out.println("vector集合中的元素:" + vector); } }
- 移除指定元素。
public synchronized boolean removeElement(Object obj) { modCount++; int i = indexOf(obj); if (i >= 0) { removeElementAt(i); return true; } return false; }
- 示例:
package day18; import java.util.Vector; /** * @motto: 一身转战三千里,一剑可当百万兵。 * @author: 不为往事扰,余生只爱笑。 * @version: 1.0 * @since: 2019-06-18 */ public class CollectionTest { public static void main(String[] args) { Vector<String> vector = new Vector<>(); vector.addElement("aaa"); vector.addElement("bbb"); vector.addElement("ccc"); boolean flag = vector.removeElement("aaa"); System.out.println("移除元素是否成功:" + flag); System.out.println("vector集合中的元素:" + vector); } }
- 清空所有的元素。
public synchronized void removeAllElements() { modCount++; // Let gc do its work for (int i = 0; i < elementCount; i++) elementData[i] = null; elementCount = 0; }
- 示例:
package day18; import java.util.Vector; /** * @motto: 一身转战三千里,一剑可当百万兵。 * @author: 不为往事扰,余生只爱笑。 * @version: 1.0 * @since: 2019-06-18 */ public class CollectionTest { public static void main(String[] args) { Vector<String> vector = new Vector<>(); vector.addElement("aaa"); vector.addElement("bbb"); vector.addElement("ccc"); vector.removeAllElements(); System.out.println("vector集合中的元素:" + vector); } }
4.6 面试题
- 请问ArrayList/LinkedList/Vector的异同?谈谈你的理解?ArrayList底层是什么?扩容机制?Vector和ArrayList的最大区别?
- ArrayList和LinkedList的异同:
- 二者都是线程不安全的,相对线程安全的是Vector,执行效率高。
- 此外,ArrayList是实现了基于动态数组的数据结构,LinkedList是基于链表的数据结构。对于要访问元素,ArrayList要优于LinkedList,因为LinkedList要移动指针。对于插入和删除元素,LinkedList比较占优势,因为ArrayList要移动数据。
- ArrayList和Vector的区别?
- Vector和ArrayList几乎是完全相同的,唯一的区别在于Vector是同步的,因此开销比ArrayList大,访问要慢。正常情况下,大多数的Java程序员使用ArrayList而不是Vector,因为同步是由程序员控制的。
- Vector每次扩容是2倍空间,ArrayList是1.5倍空间。
5 Collection子接口之一Set接口
5.1 Set接口概述
- Set接口是Collection的子接口,Set接口没有提供额外的方法。
- Set集合不允许包含相同的元素,如果把两个相同的元素加入的Set集合中,则会添加操作失败。
- Set判断两个对象是否相同,会调用equals()和hashCode()(对于HashSet来说)。
5.2 Set实现类之一HashSet
- HashSet是Set接口的典型实现,大多数时候使用Set集合时都使用这个实现类。
- HashSet按照Hash算法来存储集合中的元素,因为具有很好的存取、查找、删除性能。、
- HashSet具有以下特点:
- 不能保证元素的排列顺序。
- HashSet不是线程安全的。
- 集合元素可以是null。
- hashSet集合判断两个元素相等的标准:
- 两个元素的hashCode()方法返回值相等。
- 两个元素的equals()方法返回值也相等。
- 对于存放在Set容器中的对象,对应的类一定要重写equals()方法和hashCode()方法,以实现对象相等的原则。
- 示例:
package day18; import java.util.Objects; /** * @motto: 一身转战三千里,一剑可当百万兵。 * @author: 不为往事扰,余生只爱笑。 * @version: 1.0 * @since: 2019-06-22 */ public class Person { private String name; private Integer age; public Person() { } public Person(String name, Integer age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return Objects.equals(name, person.name) && Objects.equals(age, person.age); } @Override public int hashCode() { return Objects.hash(name, age); } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
package day18; import java.util.HashSet; import java.util.Set; /** * @motto: 一身转战三千里,一剑可当百万兵。 * @author: 不为往事扰,余生只爱笑。 * @version: 1.0 * @since: 2019-06-18 */ public class CollectionTest { public static void main(String[] args) { Person p1 = new Person("张三",60); Person p2 = new Person("张三",61); Person p3 = new Person("李四",16); Person p4 = new Person("张三",60); Set<Person> set = new HashSet<>(); set.add(p1); set.add(p2); set.add(p3); set.add(p4); System.out.println("集合中的元素:" + set); } }
5.3 Set实现类之一LinkedHashSet
- LinkedHashSet是HashSet的子类。
- LinkedHashSet根据元素的hashCode值来决定元素的存储位置,但它同时使用双向链表维护元素的次序,这使得元素看起来是以插入的顺序保存的,
- LinkedHashSet插入性能要略低于HashSet,但在迭代访问Set里面的全部元素时有很好的性能。
- LinkedHashSet不允许集合元素重复。
- 示例:
package day18; import java.util.Objects; /** * @motto: 一身转战三千里,一剑可当百万兵。 * @author: 不为往事扰,余生只爱笑。 * @version: 1.0 * @since: 2019-06-22 */ public class Person { private String name; private Integer age; public Person() { } public Person(String name, Integer age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return Objects.equals(name, person.name) && Objects.equals(age, person.age); } @Override public int hashCode() { return Objects.hash(name, age); } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
package day18; import java.util.LinkedHashSet; import java.util.Set; /** * @motto: 一身转战三千里,一剑可当百万兵。 * @author: 不为往事扰,余生只爱笑。 * @version: 1.0 * @since: 2019-06-18 */ public class CollectionTest { public static void main(String[] args) { Person p1 = new Person("张三",60); Person p2 = new Person("张三",61); Person p3 = new Person("李四",16); Person p4 = new Person("张三",60); Set<Person> set = new LinkedHashSet<>(); set.add(p1); set.add(p2); set.add(p3); set.add(p4); System.out.println("集合中的元素:" + set); } }
5.4 Set实现类之一TreeSet
- TreeSet底层是红黑树。
- TreeSet主要实现的功能有自然排序和自定义排序。
- 示例:自然排序。
package day18; import java.util.Objects; /** * @motto: 一身转战三千里,一剑可当百万兵。 * @author: 不为往事扰,余生只爱笑。 * @version: 1.0 * @since: 2019-06-22 */ public class Person implements Comparable<Person>{ private String name; private Integer age; public Person() { } public Person(String name, Integer age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return Objects.equals(name, person.name) && Objects.equals(age, person.age); } @Override public int hashCode() { return Objects.hash(name, age); } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } @Override public int compareTo(Person o) { //如果年龄相同,根据姓名排序 int compare = this.getAge().compareTo(o.getAge()); if(0== compare){ compare = this.getName().compareTo(o.getName()); } return compare; } }
package day18; import java.util.Set; import java.util.TreeSet; /** * @motto: 一身转战三千里,一剑可当百万兵。 * @author: 不为往事扰,余生只爱笑。 * @version: 1.0 * @since: 2019-06-18 */ public class CollectionTest { public static void main(String[] args) { Set<Person> set = new TreeSet<>(); set.add(new Person("张三",16)); set.add(new Person("王五",50)); set.add(new Person("田七",34)); set.add(new Person("李四",34)); System.out.println("集合中的元素是:" + set); } }
- 示例:自定义排序
package day18; import java.util.Objects; /** * @motto: 一身转战三千里,一剑可当百万兵。 * @author: 不为往事扰,余生只爱笑。 * @version: 1.0 * @since: 2019-06-22 */ public class Person { private String name; private Integer age; public Person() { } public Person(String name, Integer age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return Objects.equals(name, person.name) && Objects.equals(age, person.age); } @Override public int hashCode() { return Objects.hash(name, age); } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
package day18; import java.util.Comparator; import java.util.Set; import java.util.TreeSet; /** * @motto: 一身转战三千里,一剑可当百万兵。 * @author: 不为往事扰,余生只爱笑。 * @version: 1.0 * @since: 2019-06-18 */ public class CollectionTest { public static void main(String[] args) { Set<Person> set = new TreeSet<>(new Comparator<Person>() { @Override public int compare(Person o1, Person o2) { //如果年龄相同,根据姓名排序 int compare = o1.getAge().compareTo(o2.getAge()); if(0== compare){ compare = o1.getName().compareTo(o2.getName()); } return compare; } }); set.add(new Person("张三",16)); set.add(new Person("王五",50)); set.add(new Person("田七",34)); set.add(new Person("李四",34)); System.out.println("集合中的元素是:" + set); } }