Day_19 【Java基础】集合Collection(List、Set)
2021/11/24 1:10:28
本文主要是介绍Day_19 【Java基础】集合Collection(List、Set),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
对于数据的存储,我们已经介绍了数组,但是数组存储存在着很多的不足,如:
① 一旦初始化以后,其长度就不可修改
② 对于添加、删除、插入数据等操作非常不便,效率不高
③ 数组存储数据的特点:有序、可重复。对于无序、不可重复的需求,不能满足
④ 获取数组中实际元素的个数的需求,数组没有现成的属性或方法可用
Java集合分为Collection和Map两种体系
java集合超详解
一.Collection接口
Collection接口用于存储单列数据,
1)List接口:元素有序、可重复的集合
2)Set接口:元素无序、不可重复的集合
1.Collection接口中的主要方法
//Collection集合的主要方法说明 public class CollectionTest { public static void main(String[] args) { Collection arrayList = new ArrayList(); Collection arrayList1 = new ArrayList(); //1.add(object obj):向集合中添加元素 arrayList.add("hello"); arrayList.add(123); arrayList1.add('A'); arrayList1.add(new String("中国")); //2.size():返回集合元素个数 System.out.println(arrayList.size()); //3.addAll(Collection c):将指定集合c中的元素添加到指定集合中 arrayList.addAll(arrayList1); System.out.println(arrayList.size()); //4.clear():删除集合中的所有元素 //arrayList.clear(); System.out.println(arrayList.size()); //5.isEmpty():判断当前集合是否为空 System.out.println(arrayList.isEmpty()); //6.contains(object obj):判断当前集合是否包含指定元素 //注意:此时实际调用的是实际对象obj重写后的equals()方法,若没有重写,则调用的是Object类中的equals()方法== System.out.println(arrayList1.contains(new String("中国")));//true //7.containsAll(collection c):判断该集合是否包含指定集合c中所有的元素 System.out.println(arrayList.containsAll(arrayList1)); System.out.println(arrayList); //8.equals(collection c):判断该集合是否和指定集合c相等(元素相同,注意集合有序时还要顺序相同) System.out.println(arrayList.equals(arrayList1)); //9.remove(object o):删除该集合中指定的元素 System.out.println(arrayList.remove(123)); System.out.println(arrayList); //10.removeAll(collection c):删除包含指定集合c中所有的元素,返回boolean值 System.out.println(arrayList.removeAll(arrayList1));//true //11.retainAll(Collection c):保留包含指定集合c中所有的元素 System.out.println(arrayList); System.out.println(arrayList1); System.out.println(arrayList.retainAll(arrayList1));//true //12.hashCode();返回当前对象的哈希值 System.out.println(arrayList.hashCode()); //13.toArray():集合--->数组 Object[] array = arrayList1.toArray(); for(int i=0;i<array.length;i++){ System.out.print(array[i]+"\t"); } System.out.println(); //扩展:数组--->集合 List<String> strings = Arrays.asList(new String[]{"AA", "BB", "CC"}); System.out.println(strings); List<int[]> ints = Arrays.asList(new int[]{1, 1, 3, 44}); System.out.println(ints);//[[I@6d6f6e28]认为是一个元素,要写成对应的包装类就可以了 List<Integer> integers = Arrays.asList(new Integer[]{11, 22, 33}); System.out.println(integers); } }
2.Collection集合中元素的遍历
迭代器模式:提供了一种方法访问一个容器对象中各个元素,而不需要暴露对象的内部细节。
(1)迭代器实现集合遍历
@Test//iterator迭代器,实现集合的遍历操作。 public void test01(){ Collection arrayList = new ArrayList(); arrayList.add("ABC"); arrayList.add(new String("中国")); arrayList.add(123); //① next():迭代中的下一个元素 ② hasNext():判断下一个元素是否存在 Iterator iterator = arrayList.iterator(); while(iterator.hasNext()){ System.out.println(iterator.next()); } }
集合对象每次调用iterator()方法都得到一个全新的迭代器对象,默认游标都在集合的第一个元素之前,此外,迭代器本身不存储数据,只是用于遍历集合。
(2)增强for循环实现集合遍历
@Test//增强for循环遍历集合、数组 public void test03(){ Collection arrayList = new ArrayList(); arrayList.add("ABC"); arrayList.add(new String("中国")); arrayList.add(123); for(Object obj: arrayList){//实际就是将值赋值给obj后输出 System.out.println(obj); } }
3.使用迭代器删除指定的元素
@Test public void test02(){ Collection arrayList = new ArrayList(); arrayList.add("ABC"); arrayList.add(new String("中国")); arrayList.add(123); Iterator iterator = arrayList.iterator(); while(iterator.hasNext()){ //iterator.remove(); Object next = iterator.next();//必须先next(),后remove(),否则会IllegalStateException if(next.equals("ABC")){ iterator.remove(); } } }
二.List接口
List集合元素有序、可重复,实现了动态”数组“,线性存储,可以用于替换原有的数组。
1.ArrayList(最常用)
JDK 7下:
源码分析:ArrayList list = new ArrayList();底层是创建了长度为10的Object[] elementData数组,执行list.add(数据)时,当添加的个数超过10个,就会扩容为原来容量的1.5倍,并将原来的数据复制到新的list中。
开发建议使用带参数的构造器,指定长度:ArrayList list = new ArrayList(int Capacity);
JDK 8以后
源码分析: ArrayList list = new ArrayList();底层Object[] elementData初始化为{},当执行第一次list.add()后,才创建了长度为10的数组,后续操作和上述一样实现扩容。
List常用方法
Lis接口t继承自Collection接口,允许出现重复的元素,元素有序,可以使用索引访问,不但继承了Collection的全部方法,还增加了一些特有方法:
public class ListTest { public static void main(String[] args) { ArrayList arrayList = new ArrayList(); List list = Arrays.asList(1, 2, 3, 5); //1.boolean add(object obj):向集合中添加一个元素 arrayList.add("Hello"); arrayList.add(111); arrayList.add(true); arrayList.add(new String("设计模式")); System.out.println(arrayList); //2.boolean addAll(Collection c):将指定的集合添加到该集合中 arrayList.addAll(list); System.out.println(arrayList); //3.Object set(int index,Object element):修改指定索引处的元素,返回修改后的结果 System.out.println(arrayList.set(0,"小王")); //4.Object get(int index):返回索引位置处的元素 System.out.println(arrayList.get(0)); //5.Object remove(int index):删除指定位置的元素,返回删除的元素 //Object remove(object obj): System.out.println(arrayList.remove(0)); //6.void add(int index,Object obj):在指定的位置插入元素,返回插入后的集合 arrayList.add(0,"小吕"); System.out.println(arrayList); //7.int size():返回该集合的长度 System.out.println(arrayList.size()); //8.List subList(int fromIndex,int toIndex):返回索引之间的子集合(左闭右开),原集合不变 System.out.println(arrayList.subList(1,5)); System.out.println(arrayList); } }
集合三种遍历操作:
@Test public void test01(){ ArrayList arrayList = new ArrayList(); arrayList.add("Hello"); arrayList.add(111); arrayList.add(true); arrayList.add(new String("设计模式")); //1.iterator迭代器 Iterator iterator = arrayList.iterator(); while (iterator.hasNext()){ System.out.print(iterator.next()+"\t"); } System.out.println(); //2.增强for循环 for(Object obj: arrayList){ System.out.print(obj+"\t"); } System.out.println(); //3.普通for循环 for(int i=0;i<arrayList.size();i++){ System.out.println(arrayList.get(i)+"\t");//使用索引访问集合元素 } }
2.LinkedList
源码分析:LinkedList linkedList = new LinkedList();内部声明了Node类型的first和last属性维护一个双向循环链表,默认值为null;当执行linkedList .add(123);将123封装到Node中,创建了Node对象。
LinkedList中部分常见的特有方法
public class ListTest02 { public static void main(String[] args) { LinkedList linkedList = new LinkedList(); //1.void add(Object obj):添加元素 linkedList.add("Java"); //2.void add(int index,E element):指定位置插入指定元素 linkedList.add(0,"设计模式"); //3.void addFirst(Object obj):将指定元素插入集合开头 linkedList.addFirst(123); //4.boolean offer(Object obj):向集合尾部追加元素 System.out.println(linkedList.offer("offer"));//true //5.void push(Object obj):向集合头部追加元素 linkedList.push(true); System.out.println(linkedList);//[true, 123, 设计模式, Java, offer] //6.Object poll():移除并返回第一个元素 System.out.println(linkedList.poll());//true //7.Object peek():获取集合中的第一个元素 Object peek = linkedList.peek(); System.out.println(peek);//123 System.out.println(linkedList);//[123, 设计模式, Java, offer] //8.Object removeFirst():删除集合中第一个元素,返回删除的元素 System.out.println(linkedList.removeFirst());//123 //9.Object pollLast():删除集合最后一个元素,返回删除的元素 System.out.println(linkedList.pollLast());//offer System.out.println(linkedList);//[设计模式, Java] } }
3.Vector
Vector线程安全,在JDK 7和JDK 8使用Vector()构造器创建时创建的数组长度为10,扩容方面扩容为原来长度的2倍。
三.Set接口
Set接口也继承自Collection接口,底层数组长度为16,但未对Collection接口中的方法进行扩充,Set接口中的元素无序,不可重复,添加对象时该对象所在的类必须重写hashCode()和equals()方法,判断两个对象相同使用equals()方法。
① 无序性:不等于随机性,存储的元素不是连续存储,而是根据hash值存储。
② 不可重复性:当向HashSet集合中添加元素时,首先会调用该元素的hashCode()方法来确定该元素的存储位置,然后再调用元素的equals()方法来确保该位置没有重复元素。
1.HashSet
作为Set的主要实现类,线程不安全,底层是数组加链表,可以存储null值。
public class HashSetTest { public static void main(String[] args) { HashSet hashSet = new HashSet(); hashSet.add(123); hashSet.add(true); hashSet.add(new String("Java")); hashSet.add(new User("小王", 18)); hashSet.add(new User("小王", 18)); Iterator iterator = hashSet.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } } } class User{ private String name; private int age; public User() { } public User(String name, int age) { this.name = name; this.age = age; } @Override public boolean equals(Object o) { System.out.println("User类的equals方法调用了..."); if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; return age == user.age && Objects.equals(name, user.name); } @Override public int hashCode() { return Objects.hash(name, age); } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
1.1LinkedHashSet:
作为HashSet的子类,遍历其内部数据时,可以按照添加的顺序输出,对于频繁的遍历操作,LinkedHashset效率高于HashSet。
public class LinkedHashSetTest { public static void main(String[] args) { LinkedHashSet linkedHashSet = new LinkedHashSet(); linkedHashSet.add("Java"); linkedHashSet.add(1234); linkedHashSet.add(new String("设计模式")); linkedHashSet.add(true); Iterator iterator = linkedHashSet.iterator(); while (iterator.hasNext()){ System.out.print(iterator.next()+"\t"); } } }
2.TreeSet
TreeSet是Set接口的一个实现类,底层采用平衡二叉树存储元素,使得TreeSet集合中不存在相同的元素,并且可以对元素加进行排序。要求向TreeSet中添加的元素必须是相同类的对象。
① 自然排序:比较两个对象是否相同的标准为: compareTo()返回0,不再是equals().
public class TreeSetTest {//TreeSet自然排序实现 public static void main(String[] args) { TreeSet treeSet = new TreeSet(); treeSet.add(new Person(18,"ALi")); treeSet.add(new Person(18,"Jhon")); treeSet.add(new Person(17,"Jack")); treeSet.add(new Person(19,"Tom")); Iterator iterator = treeSet.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } } } class Person implements Comparable{ private int age; private String name; public Person(int age, String name) { this.age = age; this.name = name; } 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; } @Override public String toString() { return "Person{" + "age=" + age + ", name='" + name + '\'' + '}'; } @Override public int compareTo(Object o) {//按age排序,年龄相同时按name排序 if(o instanceof Person){ Person p = (Person)o; int num = Integer.compare(this.age,p.age); if(num!=0){ return num; }else{ return this.name.compareTo(p.name); } }else throw new RuntimeException("输入的类型不匹配..."); } }
② 定制排序:比较两个对象是否相同的标准为: compare()返回0,不再是equals().
public class TreeSetTest01 { public static void main(String[] args) { Comparator comparator = new Comparator(){ @Override public int compare(Object o1, Object o2) { if(o1 instanceof Animal && o2 instanceof Animal){ Animal o11 = (Animal) o1; Animal o21 = (Animal) o2; return Integer.compare(o11.getAge(),o21.getAge());//比较age,如果age相同,不再存储 } throw new RuntimeException("传入的类型不匹配..."); } }; TreeSet treeSet = new TreeSet(comparator);//指定是定制排序 treeSet.add(new Animal(18,"ALi")); treeSet.add(new Animal(18,"Jhon")); treeSet.add(new Animal(17,"Jack")); treeSet.add(new Animal(19,"Tom")); Iterator iterator = treeSet.iterator(); while (iterator.hasNext()){ System.out.println(iterator.next()); } } } class Animal { private int age; private String name; public Animal(int age, String name) { this.age = age; this.name = name; } 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; } @Override public String toString() { return "Animal{" + "age=" + age + ", name='" + name + '\'' + '}'; } }
面试题:
1.ArrayList、LinkedList、Vector三者有何异同?
相同:三者都实现了List接口,存储有序、可重复的元素,动态存储
不同:
ArrayList:List主要实现方式,底层使用Object[] elementData存储,线程不安全,效率高
LinkedList:底层使用双向链表存储,对于频繁的插入、删除操作效率高
Vector:底层使用Object[] elementData存储,线程安全、效率低
2.输出下列程序的运行结果
@Test public void test02(){ ArrayList arrayList = new ArrayList(); arrayList.add(1); arrayList.add(2); arrayList.add(3); updateList(arrayList); System.out.println(arrayList); } public void updateList(List list){ //list.remove(2);//输出[1, 2] list.remove(new Integer(2));//输出[1, 3] }
方式1是索引,删除的是索引位置的元素
方式2是元素,删除的是元素
这篇关于Day_19 【Java基础】集合Collection(List、Set)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-27消息中间件底层原理资料详解
- 2024-11-27RocketMQ底层原理资料详解:新手入门教程
- 2024-11-27MQ底层原理资料详解:新手入门教程
- 2024-11-27MQ项目开发资料入门教程
- 2024-11-27RocketMQ源码资料详解:新手入门教程
- 2024-11-27本地多文件上传简易教程
- 2024-11-26消息中间件源码剖析教程
- 2024-11-26JAVA语音识别项目资料的收集与应用
- 2024-11-26Java语音识别项目资料:入门级教程与实战指南
- 2024-11-26SpringAI:Java 开发的智能新利器