JAVA day18,19 单列集合Collection:List(ArrayList,LinkedList,Vector)、Queue(Deque)、Set(HashSet,TreeSet),比较器
Collection单列集合
所有超级接口:
Iterable<E>
所有已知子接口:
BeanContext, BeanContextServices, BlockingDeque<E>, BlockingQueue<E>, Deque<E>, List<E>, NavigableSet<E>, Queue<E>, Set<E>, SortedSet<E>
一、List
所有已知实现类:
AbstractList, AbstractSequentialList, ArrayList, AttributeList, CopyOnWriteArrayList, LinkedList, RoleList, RoleUnresolvedList, Stack, Vector
1.特点
- 它是⼀个元素存取有序的集合。例如,存元素的顺序是11、22、33。那么集合中,元素的存储就是按照11、22、33的顺序完成的)
- 集合中允许有null值
- 它是⼀个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是⼀个道理)
- 集合中可以有重复的元素,通过元素的equals⽅法,来⽐较是否为重复的元素。
2. 常用API
List作为Collection集合的⼦接⼝,不但继承了Collection接⼝中的全部⽅法,⽽且还增加了⼀些根据元素索引来操作集合的特有⽅法,如下:
3.List接口的实现类
1.ArrayList
java.util.ArrayList 集合数据存储的结构是数组结构。元素增删慢,查找快,由于⽇常开发中使⽤最多的功能为查询数据、遍历数据,所以 ArrayList 是最常⽤的集合。
特点:
1.按照顺序排列,每个元素都带有标号;2.除了有标号是连续的,内存中的物理空间也是连续的。
底层使用的数据结构:顺序结构;
顺序结构底层实现:数组;
优缺点:查询快;增删慢,内存的物理空间是连续的,利用不到碎片空间。
import java.util.ArrayList;
// ArrayList是子接口List的实现类之一
public class ArrayListDemo01 {public static void main(String[] args) {ArrayList<Object> a = new ArrayList<Object>();a.add(2);a.add(23);System.out.println(a);//[2, 23]//1.向集合(this)中末尾添加元素a.add(2,55);System.out.println(a);//[2, 23, 55]//2.向集合index的位置中插入obj元素a.add(1,"哈哈");System.out.println(a);//[2, 哈哈, 23, 55]//3.删除指定位置(index)上的元素,并且返回删除的元素//比如删除下标是2的元素a.remove(2);System.out.println(a);//[2, 哈哈, 55]//4.删除第一个指定元素(obj)a.remove(0);System.out.println(a);//[哈哈, 55]//5.替换指定位置上的元素,替换成obj,并且返回被替换的元素a.set(1,"嘻嘻");System.out.println(a);//[哈哈, 嘻嘻]//6.从集合中获得指定位置(index)的元素//比如下标是1位置上的元素System.out.println(a.get(1));//嘻嘻//7.获得集合中的元素个数System.out.println(a.size());//2//8.判断集合中是否存在指定元素objSystem.out.println(a.contains("嘻嘻"));//true//9.判断集合是否为空:没有有效元素是空System.out.println(a.isEmpty());//false// 10.打印出在集合中的有效元素for (Object obj : a) {if (a.isEmpty() == false && obj != null){System.out.println(a);}}}
}
2.LinkedList
特点:
1.LinkedList是双向链表
2.链表是内存中固定顺序,但是他的物理空间不连续
3.没有下标
4.所有节点的访问,都必须通过头节点(next)/尾节点(pre)
5.head(头节点): 只存next,不存data;last(尾节点): 只存pre,不存data
6.head.next = null -> 空链表;last.pre = null -> 空链表
底层使用的数据结构:链式结构;
链式结构底层实现:链表:节点(data数据 + next下一个节点的引用);
优缺点:插入删除效率高,不需要连续的内存物理空间,空间利用率高;查找慢
特有API:(只要带有First/last的方法)
/*LinkedList常用API:void addFirst(E e)void addLast(E e)E getFirst()E getLast()E remove(int index)E removeFirst()E removeLast()*/import java.util.LinkedList;public class LinkedApiDemo {public static void main(String[] args) {LinkedList<Object> linked = new LinkedList<>();linked.add(23);linked.add(15.6);linked.add(0,false);System.out.println(linked);//[false, 23, 15.6]linked.addFirst(true);System.out.println(linked);//[true, false, 23, 15.6]linked.addLast(888);System.out.println(linked);//[true, false, 23, 15.6, 888]linked.removeFirst();System.out.println(linked);//[false, 23, 15.6, 888]Object o = linked.getLast();System.out.println(o);//888}
}
3.Vector
Vector
类可以实现可增长的对象数组。与数组一样,它包含可以使用整数索引进行访问的组件。但是,Vector
的大小可以根据需要增大或缩小,以适应创建 Vector
后进行添加或移除项的操作。
特点:
特点跟ArrayList 一样,特别的是,Vector上带有线程同步锁(synchronized),所以是线程安全的,效率低。
tips:ArrayList 和 Vector的区别
a.线程安全区别
ArrayList不带锁,线程不安全,效率高
Vector带锁,线程安全,效率低
b.扩容问题区别
ArrayList扩容为原容量的1.5倍
Vector扩容为原容量的2倍
二、Queue
Queue也是Collection接口的子接口,在处理元素前用于保存元素的 collection。除了基本的 Collection
操作外,队列还提供其他的插入、提取和检查操作。每个方法都存在两种形式:一种抛出异常(操作失败时),另一种返回一个特殊值(null 或 false,具体取决于操作)。插入操作的后一种形式是用于专门为有容量限制的 Queue 实现设计的;在大多数实现中,插入操作不会失败。
1.特点
1.先进先出;后进后出。2.队列也是线性结构,有顺序的,但是本身没有标号。
底层使用的数据结构:顺序(数组)或者链式(链表);
2.API
offer() - 向队列尾部追加元素
poll() - 向队列头部取出元素(出队列)
peek() - 向队列头部获取元素(队列不变)
import java.util.LinkedList;
import java.util.Queue;//队列 offer peek poll
public class QueueDemo {public static void main(String[] args) {//创建对象Queue底层实现是链表Queue<Object> qu = new LinkedList<>();//添加offerqu.offer(12);qu.offer("哈哈哈");qu.offer(true);System.out.println(qu);//[12, 哈哈哈, true]//查看peek(出列)Object pe = qu.peek();System.out.println(pe);//12System.out.println(qu);//[12, 哈哈哈, true]//poll(出列)Object po =qu.poll();System.out.println(po);//12System.out.println(qu);//[哈哈哈, true]}}
3.子接口(Deque)
Deque 是 Queue接口的子接口,一个线性 collection,支持在两端插入和移除元素。名称 deque 是“double ended queue(双端队列)”的缩写,通常读为“deck”。大多数 Deque 实现对于它们能够包含的元素数没有固定限制,但此接口既支持有容量限制的双端队列,也支持没有固定大小限制的双端队列。
特点:
1.作为双端队列 - 先进先出
作为栈 - 先进后出
2.只能通过方法区分是队列/栈
底层使用的数据结构:顺序(数组)或者链式(链表);
常用API:
作为双端队列:
带有First()/Last()
作为栈:
push() - 压栈
pop() - 弹栈
双端队列代码
import java.util.Deque;
import java.util.LinkedList;//双端队列
public class DequeDemo {public static void main(String[] args) {Deque<Object> de = new LinkedList<>();de.offer("55");de.offerFirst(false);//头添加de.offer(666);System.out.println(de);//[false, 55, 66]de.offerLast(889);//尾添加System.out.println(de);//[false, 55, 666, 889]Object pe = de.peek();System.out.println(pe);//falseObject pe1 = de.peekFirst();System.out.println(pe1);//falseObject pe2 = de.peekLast();System.out.println(pe2);//889System.out.println(de);//[false, 55, 666, 889]Object po = de.poll();System.out.println(po);//falseSystem.out.println(de);//[55, 666, 889]Object po1 = de.pollFirst();System.out.println(po1);//55System.out.println(de);//[666, 889]Object po2 = de.pollLast();System.out.println(po2);//889System.out.println(de);//[666]}
}
栈代码:
import java.util.Deque;
import java.util.LinkedList;public class DequeStackDemo {public static void main(String[] args) {Deque<Object> des = new LinkedList<>();//存入 实现栈 先进后出des.push(222);des.push(999);System.out.println(des);//[999, 222]des.pop();System.out.println(des);//[222]}
}
三、Set
所有已知子接口:
NavigableSet<E>, SortedSet<E>
所有已知实现类:
AbstractSet, ConcurrentSkipListSet, CopyOnWriteArraySet, EnumSet, HashSet, JobStateReasons, LinkedHashSet, TreeSet
1.特点
- API跟Collection里的完全一致。
- Set集合截取Map(映射表)。
- Set集合的物理空间是不连续的,添加没有顺序(不是随机,是不按添加的顺序输出)
- Set集合不允许有重复值,值是唯一的。使用equals()判断元素是否重复。
- Set集合允许null值。
2.Set接口的实现类
1.HashSet
b.如果该位置上没有元素,则直接存入
c.如果该位置上有元素,则调用equals()和该位置上所有元素进行比较
d.如果相同,则覆盖原来的数据
e.如果不相同,则存入该链表的末尾
HashSet所使用的数据结构:哈希表(Hash表)
代码举例:
import java.util.HashSet;
import java.util.Set;public class HashSetDemo {public static void main(String[] args) {Set<Object> set = new HashSet<>();set.add(222);set.add("困死了");set.add(2.13);set.add(null);//允许空值System.out.println(set);//[null, 2.13, 困死了, 222] ---> 输出无序set.add(2.13);System.out.println(set);//[null, 2.13, 困死了, 222] ---> 且不允许有重复值 因为判断了两值相等,所以覆盖了//原因//HashSet --- > Set 底层实现其实是数组加链表实现的 在数组的每个位置上 都存在一个链表的结构//存数据时,先计算数据的hashcode的值用来判断存放位置。//然后判断该位置上是否存在元素,如果没有,存入链表;如果有,需要equals判断//两个值是否相等,不相等则存入链表末端,相等则覆盖之前的值。set.remove(null);System.out.println(set);//[2.13, 困死了, 222]}
}
HashSet存储⾃定义类型元素
import java.util.Objects;//实体类
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;}@Overridepublic 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);}@Overridepublic int hashCode() {return Objects.hash(name, age);}@Overridepublic String toString() {return "Student{"+ name + ","+ age+"}";}
}import java.util.HashSet;//测试存放数据的原因 hashcode equals
public class HashSetTest {public static void main(String[] args) {Student stu1 = new Student("lucy",15);Student stu2 = new Student("tony",15);Student stu3 = new Student("jack",13);HashSet<Student> set = new HashSet<Student>();set.add(stu1);set.add(stu2);set.add(stu3);System.out.println(set);//重写了toString方法//[Student{lucy,15}, Student{tony,15}, Student{jack,13}]set.remove(stu1);System.out.println(set);}
}
2.TreeSet
在说这个实现类之前,先学习一下树,跟比较器。
树
树:树是n个结点的有限集合,有且仅有一个根结点,其余结点可分为m个根结点的子树。
⼆叉树 : binary tree ,是每个结点不超过 2 的有序 树( tree ) 。⼆叉树是每个节点最多有两个⼦树的树结构。顶上的叫根结点,两边被称作 “ 左⼦树 ” 和 “ 右⼦树 ” 。
满二叉树:高度为h,由2^h-1个节点构成的二叉树称为满二叉树。
完全二叉树:完全二叉树是由满二叉树而引出来的,若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数(即1~h-1层为一个满二叉树),第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。
平衡二叉树:当且仅当两个子树的高度差不超过1时,这个树是平衡二叉树。(同时是排序二叉树)平衡二叉树,又称AVL树。它或者是一棵空树,或者是具有下列性质的二叉树:它的左子树和右子树都是平衡二叉树,且左子树和右子树的高度之差之差的绝对值不超过1.。
二叉树的遍历
前序遍历(前根遍历):根——>左——>右
中序遍历(中根遍历):左——>根——>右
后序遍历(后根遍历):左——>右——>根
3.比较器
public int compareTo(Student o) :⽐较其两个参数的顺序。 比较 this 和 obj
this. 比 obj 小
this. 比 obj 大
this. 和 obj 相同
this在前,obj在后 正序
obj在前,this在后 倒序
基于 TreeMap
的 NavigableSet
实现。使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator
进行排序,具体取决于使用的构造方法。
代码:
import java.util.TreeSet;public class TreeSet01 {public static void main(String[] args) {//默认排序方法是中序排序TreeSet<Integer> treeSet = new TreeSet<>();treeSet.add(555);treeSet.add(2);treeSet.add(5);System.out.println(treeSet);//[2, 5, 555]/*泛型是String:1.默认按照字典顺序排序2.如果相同字母,但是长度不同,短在前,长在后3.全小写或者是全大写,按字典顺序排序,首字母相同查看第二位*/TreeSet<String> tree1 = new TreeSet<>();tree1.add("marry");tree1.add("marry");//一样的值就进行覆盖tree1.add("lucy");tree1.add("tom");tree1.add("jack");tree1.add("rose");System.out.println(tree1);//[jack, lucy, marry, rose, tom]/*1.大写字母在前,小写字母在后因为ASCII码值对应的 A = 65 a = 97*/TreeSet<Character> tree2 = new TreeSet<>();tree2.add('a');tree2.add('b');tree2.add('B');tree2.add('A');System.out.println(tree2);//[A, B, a, b]}
}
自定义tree
import java.util.Comparator;/*自定义实现二叉树*/
public class Tree<T> {//内部类private class Node<T>{private T data;private Node left;private Node right;Node(T data){this.data = data;}}//根节点:private Node<T> root;//定义一个内部的方法 - 递归方式实现private void addNode(Node node,T t){if(((Comparable)t).compareTo(node.data) > 0){if (node.right == null){node.right = new Node<T>(t);return;}addNode(node.right,t);}else if(((Comparable)t).compareTo(node.data) < 0){if (node.left == null){node.left = new Node<T>(t);return;}addNode(node.left,t);}}//add()public void add(T t){if (root == null){root = new Node<>(t);return;}addNode(root,t);}//在内部看来: 对每一个节点进行遍历 - 递归private void travelNode(Node node){if(node.left != null){travelNode(node.left);}System.out.println(node.data);if(node.right != null){travelNode(node.right);}}//对插入的数据进行遍历 - 按照从小到大的顺序进行排序public void travel(){//对数据进行排序travelNode(root);}/*public void add(T t){//判断是否存在根节点if(root == null){root = new Node<T>(t);return;}Node node = root;Node parentNode;while (true){parentNode = node;//((Comparable)t).compareTo()if(((Comparable)t).compareTo(node.data) > 0){//存在根节点的右边node = node.right;if(node == null){parentNode = new Node(t);return;}}else if(((Comparable)t).compareTo(node.data) < 0){//存在根节点的左边node = node.left;if(node == null){parentNode = new Node(t);return;}}}}*/
}public class TreeSetTest {public static void main(String[] args) {Tree tree = new Tree();tree.add(55);tree.add(222);tree.add(888);tree.travel();/** 55222888* */}
}
比较器:
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;/*
* java的排序
* 1.自然排序(默认排序)
* 2.自定义排序
*
* 数组Arrays
* Arrays.sort---->默认排序
*
* 集合
* List
* Collections.sort ---->默认排序
*
* Queue Stark 队列跟栈 就不能进行排序 因为位置都是固定的
*
* Set
* TreeSet set = new TreeSet(); ----> 无参就是默认排序
*
* Map
* TreeMap() map = new TreeMap();----> 无参就是默认排序
* */
public class ComparatorDemo01 {public static void main(String[] args) {//对数组排序 默认排序Integer[] arr = {2,66,9,33};System.out.println("排序前"+Arrays.toString(arr));//排序前[2, 66, 9, 33]Arrays.sort(arr);System.out.println("排序后"+Arrays.toString(arr));//排序后[2, 9, 33, 66] 默认从小到大//自定义排序Arrays.sort(arr , new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {return 0;}});//对List集合进行排序 默认ArrayList<Integer> list = new ArrayList<>();list.add(5);list.add(5);list.add(4);list.add(598);System.out.println("排序前"+list);//排序前[5, 5, 4, 598]Collections.sort(list);System.out.println("排序后"+list);//排序后[4, 5, 5, 598]//自定义list排序 就要用到比较器了//对List集合进行排序 - 指定比较器Collections.sort(list, new Comparator<Integer>() {@Overridepublic int compare(Integer o1, Integer o2) {/*return 0; 不进行排序*///return o1 - o2;//正序return o2 - o1;//倒序}});System.out.println(list);}
}
tree比较器:
import java.util.Objects;/*自定义实现类解决办法:1.在自定义的类中实现Comparable接口2.重写Comparable中的compareTo()*/
public class User implements Comparable<User>{private String name;private int age;public User(String name, int age) {this.name = name;this.age = age;}public User() {}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;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +'}';}@Overridepublic boolean equals(Object o) {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);}@Overridepublic int hashCode() {return Objects.hash(name, age);}/*return 0: 会认为传进来的所有对象都是同一个二叉树: 中序遍历左 < 根 < 右compareTo():this 和 u对比规则:this 比 u 小, 则返回负数this 和 u 相同,则返回0 -> 不存入this 比 u 大, 则返回正数this - u --> 正序u -> this --> 倒序*/@Override//重写的比较方法public int compareTo(User u) {//this(User) 和 u(User)//强制类型转换//return 0;//默认方式:从小到大进行排序 - 正序//return this.getAge() - u.getAge();if(u.getAge() != this.getAge()){return u.getAge() - this.getAge();//倒序}// 从大到小进行排序 - 倒序return u.getName().compareTo(this.getName());}
}import java.util.Comparator;
import java.util.TreeSet;/*对自定义的类进行排序自然排序 Comparable自定义排序(指定排序) Comparator*/
public class TreeSetDemo {public static void main(String[] args) {TreeSet<User> tree = new TreeSet<>();User u1 = new User("张三", 18);User u2 = new User("李四", 18);User u3 = new User("小黄", 16);User u4 = new User("小红", 21);tree.add(u1);tree.add(u2);tree.add(u3);tree.add(u4);/* 如果自定义的类没有实现Comparable接口则会:ClassCastException - 类型转换异常解决办法:1.在自定义的类中实现Comparable接口2.重写Comparable中的compareTo()*/System.out.println(tree);TreeSet<User> tree2 = new TreeSet<>(new Comparator<User>() {@Overridepublic int compare(User o1, User o2) {return o1.getName().compareTo(o2.getName());/*o1.getAge() - o2.getAge()*/}});}
}
JAVA day18,19 单列集合Collection:List(ArrayList,LinkedList,Vector)、Queue(Deque)、Set(HashSet,TreeSet),比较器相关推荐
- ArrayList, LinkedList, Vector - dudu:史上最详解
ArrayList, LinkedList, Vector - dudu:史上最详解 我们来比较一下ArrayList, LinkedLIst和Vector它们之间的区别.BZ的JDK版本是1.7.0 ...
- ArrayList,LinkedList,Vector的异同点
先总结下ArrayList和LinkedList的区别: 1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构. 2.对于随机访问get和set,ArrayLi ...
- List 系列 ArrayList LinkedList CopyOnWriteArrayList Queue系列 ArrayDeque ConcurrentLinkedDeque LinkedBlo
LinkedBlockingDeque作为一种阻塞双端队列,提供了队尾删除元素和队首插入元素的阻塞方法.该类在构造时一般需要指定容量,如果不指定,则最大容量为Integer.MAX_VALUE.另外, ...
- ArrayList ,LinkedList,Vector,StringBuilder,StringBuffer ,String,HashMap,LinkedHashMap,TreeMap
ArrayList ,LinkedList,Vector 区别和联系 从上面的类层次结构图中,我们可以发现他们都实现了List接口,它们使用起来非常相似.区别主要在于它们各自的实现,不同的实现导致了不 ...
- Collection,List,ArrayList,LinkedList集合
Collection集合 是单例集合的顶层接口,它表示一组对象,这些对象也称为Collection的元素 lJDK 不提供此接口的任何直接实现,它提供更具体的子接口(如Set和List)实现 Coll ...
- 单列集合Collection接口
集合是可以存任何类型对象,并且长度可变的类,使用时要导包,java.util.~,不知道使用什么包时可以使用通配符导出所有包,java.util.*; 集合分为单口集合Collction和双口集合Ma ...
- 黑马程序员--Java学习日记之集合(collection类与list接口)及泛型概述
------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 一,集合概念 之前我们存储大量的对象,可以使用数组: 但数组有两个缺陷: 1. ...
- java集合Collection,ArrayList,常见方法及演示。
Collection集接口方法 add(E e)添加元素; clear()清空元素; remove(E e)移除元素; size()元素数量; toArray()集合转数组; contains(E e ...
- java容器类1:Collection,List,ArrayList,LinkedList深入解读
1. Iterable 与 Iterator Iterable 是个接口,实现此接口使集合对象可以通过迭代器遍历自身元素. public interface Iterable<T> 修饰符 ...
最新文章
- Oracle\MS SQL Server的数据库多表关联更新UPDATE与多表更新
- Framework打包
- android网络重试机制,okhttp源码解析(四):重试机制
- LeetCode 1442. 形成两个异或相等数组的三元组数目(前缀异或)
- java 获取及修改系统变量
- Leetcode那点事儿
- Apple原装扫描二维码指定区域
- 狂神SpringBoot静态资源文件
- 你好,CSDN!你好,C语言!
- 安装deepin微信报错: dpkg: 依赖关系问题使得 deepin.com.wechat:i386 的配置工作不能继续 解决办法如下:
- Python爬虫初级(十一)—— Selenium 详解
- 利用原生js制作小游戏
- CSS gradient渐变之webkit核心浏览器下的使用
- opencv今犹在,不见当年引路人
- 996 log抓取过程
- 1、pinpoint-简介
- 揭秘今年Android春招面试必问问题有哪些?成功拿下大厂offer
- 为什么服务器未响应ins,9修复Instagram无法正常工作,加载或崩溃的最佳方法
- 2. 因子(factor)、缺失数据(na)、字符串、时间序列数据
- AllWinner T113 wifi tools交叉编译
热门文章
- 跌落式封隔器行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
- 电子过载继电器行业调研报告 - 市场现状分析与发展前景预测(2021-2027年)
- windows 下nodejs 升级无法通过n模块升级
- android局部翻转动画,android 围绕中心旋转动画
- 当 Windows 11 宕机时:从蓝屏死机变成“黑屏死机”!
- 图文分析:如何利用Google的protobuf,来思考、设计、实现自己的RPC框架
- 渲染百万网页,终于找到影响性能的原因了
- 泰坦尼克号上谁的生存几率更大?Kaggle 金牌得主 Python 数据挖掘框架发现真相...
- 新职业风口已至!人社部宣布这 10 个职业缺口近千万!
- 颜值即正义!颜值爆表的几个数据交互的库来啦!