欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 游戏 > 【JAVA】集合与接口

【JAVA】集合与接口

2025/4/3 21:41:44 来源:https://blog.csdn.net/weixin_53538280/article/details/146877586  浏览:    关键词:【JAVA】集合与接口

当一个程序员开始学习八股文,你就知道他要干什么了。

Java面向对象

一、集合

       对于元素的存储,一方面我们可以使用变量完成单个元素的存储,如果我们想要存储多个元素,那么我们就只需要使用数组就可以了,但是数组存储元素有很多限制,首先数组只能存储指定类型的元素并且数组的存储元素的容量是固定,对此我们可以使用集合去存储多个元素,集合相对于数组来说它所存储的元素类型更加灵活,同时集合的容量没有限制(容量的最大值我们一般达不到,并且集合会自动扩容),最重要的是集合加入了泛型。

数组和集合的区别:

  • 数组可以存储任意类型而集合不能存储基本数据类型(集合中用到了泛型)

  • 数组存储元素的容量是固定的,而集合没有固定它会自动扩容

1.1 Collection接口和Map接口

1.1.1 Collection接口

Collection集合可以用于存储单个元素。

Collection接口常见方法如下所示:

面试题:

Collection集合和数组怎么互相转换?

数组可以借助工具类Arrays.toList()讲数组转化为List集合,集合可以使用toArray将集合变为数组

Collection和Collections有什么区别?

Collection是一个接口,是所有单元素集合的接口例如set、list等,而Connctions是一个类,它是Collection的一个工具类

1.2 Map接口

Map接口和Collection接口是相对的,Map接口是一个用于存储“夫妻元素”(key-value)集合的一个接口。

1.3 集合体系

二、List接口

2.1 ArrayList

2.1.1 ArrayList的创建

@Testpublic void listCreateMethod1(){ArrayList<Integer> list = new ArrayList<>();List<String> list1 = new ArrayList<>();System.out.println(list1);}

ArrayList的底层是一个Object动态数组,该数组的初始容量为10。

2.1.2 元素的添加

@Testpublic void listDataAddMethod(){ArrayList<Integer> list = new ArrayList<>();list.add(10);list.add(30);list.add(40);System.out.println(list);}

ArrayList通过add方法进行元素的添加:首先先判断Object[] elementData的长度length,若length达到了阈值就进行扩容 接着elementData[size++] = e

2.1.3 元素的获取

1、单个元素获取

//用于获取ArrayList集合的单个元素@Testpublic void queryArrayListOneElement(){ArrayList<Integer> list = new ArrayList<>();list.add(10);list.add(30);list.add(40);Integer i1 = list.get(2);System.out.println(i1);}

2、遍历

// ArrayList集合元素的遍历@Testpublic void arrrayListElementIterator1(){ArrayList<Integer> list = new ArrayList<>();list.add(10);list.add(30);list.add(40);for (int i = 0; i < list.size(); i++) {System.out.println(list.get(i));}}// ArrayList集合元素的遍历2@Testpublic void arrrayListElementIterator2(){ArrayList<Integer> list = new ArrayList<>();list.add(10);list.add(30);list.add(40);for (Integer item:list) {System.out.println(item);}}// ArrayList集合元素的遍历3@Testpublic void arrrayListElementIterator3(){ArrayList<Integer> list = new ArrayList<>();list.add(10);list.add(30);list.add(40);// 创建迭代器Iterator<Integer> iterator = list.iterator();// 使用循环并且集合迭代器里面的hasnext和next完成元素的遍历// hasnext方法可以用于判断当前迭代器中是否还存在元素while (iterator.hasNext()){/*next相当于一个指针指向迭代迭代器里面的每一个元素当调用一次next以后指针下移*/Integer next = iterator.next();System.out.println(next);}}

注意:我们遍历迭代集合中的元素的时候,for-i循环遍历可以去修改元素,而for-each和迭代器在遍历的时候不能去修改元素,但是迭代器支持删除元素(迭代器对象提供remove方法)。

// ArrayList集合元素的遍历@Testpublic void arrrayListElementIterator1(){ArrayList<Integer> list = new ArrayList<>();list.add(10);list.add(30);list.add(40);for (int i = 0; i < list.size(); i++) {//修改元素// list.set(i,123);list.remove(list.get(i));}System.out.println(list);}2.1.4 Comparator接口// Comparator接口@Testpublic void comparatorTset1(){ArrayList<Integer> list = new ArrayList<>();list.add(10);list.add(30);list.add(40);list.add(20);list.sort(new Comparator<Integer>() {/*compare方法可以用于比较两个元素大小compare(a,b)返回值:compare返回值等于0表示a=bcompare返回值大于0表示a比b大即要把a排在b的后面compare返回值小于0表示a比b大小即把a排在b的前面*/@Overridepublic int compare(Integer integer, Integer t1) {System.out.println(integer);System.out.println(t1);System.out.println(t1 - integer);System.out.println("--------------------");return t1 - integer;}});System.out.println(list);}

2.2 LinkedList

LikedList和ArrayList用法是一样的,唯一的区别就是它们的底层实现逻辑有所区别。

public void linkedListCreated(){List<Integer> list = new LinkedList<>();}

ArrrayList的底层是Object动态数组,而LinkedList的底层是链表,数组在查询上的效率要高于链表,而元素的修改链表的效率要高于数组,因此我们在实际开发的时候要去合理的选择。

public class LInkedListModel {@Testpublic void linkedListCreated(){List<Integer> list = new LinkedList<>();list.add(10);}@Testpublic void NodeTest1(){Node<String> node1 = new Node<>("张三");Node<String> node2 = new Node<>("李四");node1.next = node2;node2.pre = node1;}}class Node<E>{E element;Node<E> next;Node<E> pre;public Node(E o){this.element = o;}}

2.3 Vector

Vcetor也是List的一个实现类,它和ArrayList的用法一样,只是底层代码所有区别,ArrayList每次扩容时候扩容1.5倍,而Vector每次扩容为1.2倍,Vector相对于ArrayList来说Vector是线程安全的(Vector使用了同步锁synchronized)。

2.4 Stack

Stack是Vector的一个子类,它严格遵循先进后出,因此对于元素的添加使用的push方法而元素的弹出使用pop。

@Testpublic void StackCreated(){Stack<Integer> stack = new Stack<>();/*peek()可以获取栈顶的元素pop()获取栈顶并将栈顶元素给弹出*/Integer peek = stack.peek();}

三、Set集合

Set集合是一个无序(存储的时候无序)集合,也就是说Set集合没有索引,并且Set集合还可以去重。

3.1 HashSet

HashSet的底层依靠的HashMap。

Set<Integer> set1 = new HashSet<>();public void createHashSet(){Set<Integer> set1 = new HashSet<>();set1.add(1);set1.add(10);set1.add(1);System.out.println(set1);}

Set集合不能通过索引去获取单个元素(Set集合没有把索引给暴露出来)。

// HashSet元素的获取@Testpublic void getHashSet(){Set<Integer> set1 = new HashSet<>();set1.add(1);set1.add(10);set1.add(1);for (Integer i:set1) {System.out.println(i);}Iterator<Integer> iterator = set1.iterator();while (iterator.hasNext()){Integer next = iterator.next();/*iterator有一个方法可以删除元素*///iterator.remove();}}

3.2 LinkedHashSet

LinkedHashSet是HashSet的一个子类,LinkedHashSet和HashSet的用法一样,只是LinkedHashSet是有序的。

@Testpublic void linkedHashSetTset(){Set<String> set1 = new LinkedHashSet<>();set1.add("张三");set1.add("王五");set1.add("张三");set1.add("李四");System.out.println(set1);}

3.3 TreeSet

TreeSet集合和HashSet集合用法一样,TreeSet集合可以对元素进行排序,需要注意的是TreeSet集合只针对String、Integer、Float等做了自然排序(默认是升序),如果说TreeSet中存储的是上述实现了自然排序的类以外都需要去实现Compartor接口并实现排序规则。

TreeSet的底层依赖于TreeMap。

@Testpublic void treeSetTest1(){Set<Integer> set1 = new TreeSet<>();set1.add(10);set1.add(3);set1.add(20);set1.add(16);set1.add(3);System.out.println(set1);}@Testpublic void treeSetTest2(){Set<Integer> set1 = new TreeSet<>(new Comparator<Integer>() {@Overridepublic int compare(Integer integer, Integer t1) {return t1 - integer;}});set1.add(10);set1.add(3);set1.add(20);set1.add(16);set1.add(3);System.out.println(set1);}@Testpublic void treeSetTest3(){Set<Student> set1 = new TreeSet<>();set1.add(new Student("张三",28));set1.add(new Student("李四",29));set1.add(new Student("赵六",28));set1.add(new Student("王五",30));System.out.println(set1);}class Student implements Comparable<Student>{String name;int age;public Student() {}public Student(String name, int age) {this.name = name;this.age = age;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +'}';}/*先按照年龄降序排序,若年龄相同则比较姓名*/@Overridepublic int compareTo(Student student) {if (this.age == student.age){return this.name.compareTo(student.name);}return student.age - this.age;}}

四、Map集合

Map集合是一个双列集合,Map集合存储的是键值对。

4.1 HashMap

@Testpublic void hashMapTest1(){Map<String,Integer> map = new HashMap<>();map.put("key1",1);map.put("key2",2);map.put("key1",3);map.put(null,4);System.out.println(map);}

HashMap在key-value时,key不能重复,value没做限制,若key重复的话则最后出现的key-value回去覆盖前面相同key的key-value,并且HashMap的key值允许为null。

HashMap的遍历可以使用foreach方法并结合lambda表达式。

@Testpublic void hashMapTest2() {Map<String,String> map = new HashMap<>();map.put("key1","张三");map.put("key2","李四");map.put("key3","王五");map.forEach((k,v)->{System.out.println(k);System.out.println(v);System.out.println("----------------");});}

HashMap在jdk7以前它的底层是由数组+链表,jdk7及以后它的底层就是数组+链表+红黑树。

HashMap时通过put方法完成元素的存储,put方法拿到key-value之后,调用了putVal方法,put方法往putVal方法里面传递了5个参数其中就包含key、value、key的hash值(hash值就是数字),putVal方法拿到key的hash值之后和n-1做逻辑与运算(n-1 & hash(key)),运算的结果用于确定key-value在数组中存储位置的索引,找到对应位置索引后就可以将key-value放置在当前索引位置下的链表上,当链表的长度达到了阈值(7)之后当前索引位置下的存储就由链表转为红黑树。

HashMap在存储的时候可能会遇到Hash冲突。

4.2 CurrentHashMap

CurrentHashMap时HashMap的一个线程安全类,HashMap是线程不安全的,CurrrentHashMap则是HashMap的一个线程安全类。

参考资料:

 Java集合框架通关指南:从数组到ArrayList的深度解剖 (qq.com)

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词