Collection、list、map、set、comparable、comparator 叁歲伎倆 2022-03-30 13:16 185阅读 0赞 # Collection # 数组: 缺点:(1)长度固定,如果要扩容等需要程序自己维护,如果要删除和插入,程序员要移动元素等 (2)数组只支持“可重复,顺序存储”特点,比较单一 集合:很多种容器 实际开发中,数据的存储特点:(1)有序的(2)无序的(3)可以重复的(4)不能重复的(5)一对一的(6)一对多… JDK在(1)数组(2)链式结构基础上,重新设计出了很多的容器类型。 \* 主要是两大类: 1、Collection:一组对象,比喻"单身party" 2、Map:键值对,(key,value),比喻“情侣party”,“家庭party" 容器有共同的行为特征,操作方式: 增、删、改、查… 把对容器的操作的行为标准化,用接口来声明。 一、java.util.Collection (一)Collection概述 Collection 层次结构 中的根接口。Collection 表示一组对象。 一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。 JDK 不提供此接口的任何直接 实现:它提供更具体的子接口(如 Set 和 List)实现。 1、List 列表:可重复的,有序的(按顺序存储) 实现类:例如ArrayList(动态数组) 2、Set 集:不可重复的,无序的(和添加顺序无关) (二)Collection的常用方法 1、添加 (1)add(Object obj):一次添加一个 (2)addAll(Collection other):一次添加多个,把other中的元素都添加到当前集合中 this = this ∪(并) other 2、删除 (1)remove(Object o) :一次删除一个 (2)removeAll(Collection other):一次删除多个 this = this - this ∩(交) other (3)clear() 3、修改:Collection根接口中没有提供修改的方法 4、查询 (1)boolean contains(Object o) :判断o是否在当前集合中 (2)boolean containsAll(Collection<?> c):判断c中的元素都在当前集合中 即判断c是否是this的子集 (3)boolean isEmpty() Collection根接口中没有提供获取一个元素的方法。 5、获取有效元素的个数 int size() 6、遍历 (1)老方法 Object\[\] toArray():如果该集合的底层实现就是数组,那么比较简单,但是如果该集合的底层不是数组,那么就比较麻烦。 无论底层怎么样,都会返回一个size长度的数组,所以比较浪费空间。 (2)foreach (2)Iterator迭代器遍历 7、其他 retainAll(Collection<?> c) :保留当前集合和c集合的交集 this = this ∩ c public class TestCollection { @SuppressWarnings("all") @Test public void test3(){ Collection c = new ArrayList(); c.add("张三"); c.add("李四"); c.add("王五"); c.add("钱七"); Collection other = new ArrayList(); other.add("王五"); other.add("赵六"); c.retainAll(other); Object[] array = c.toArray(); for (int i = 0; i < array.length; i++) { System.out.println(array[i]); } } @SuppressWarnings("all") @Test public void test2(){ Collection c = new ArrayList(); c.add("张三"); c.add("李四"); c.add("王五"); c.add("赵六"); c.add("钱七"); Collection other = new ArrayList(); other.add("王五"); other.add("赵六"); // c.remove("张三"); c.removeAll(other); Object[] array = c.toArray(); for (int i = 0; i < array.length; i++) { System.out.println(array[i]); } } @SuppressWarnings("all") @Test public void test1(){ //多态引用,关注Collection的方法,ArrayList是Collection子接口List的实现类 Collection c = new ArrayList(); c.add("张三"); c.add("李四"); Collection other = new ArrayList(); other.add("王五"); other.add("赵六"); c.addAll(other); // c.add(other); System.out.println(c.size()); Object[] array = c.toArray(); for (int i = 0; i < array.length; i++) { System.out.println(array[i]); } } } # List # /\* * java.util.List:接口 * (1)有序:可以对元素的索引index,进行控制。 * (2)可重复。 * * 常用方法: * 继承了Collection,因此,Collection的所有的方法和操作它都有。 * List还增加了很多方法,这些方法都和index相关。 * * 1、添加 * add(int index, E element) :在index位置插入一个元素 * addAll(int index, Collection<? extends E> c):在index位置插入多个元素 * * 2、删除 * remove(int index) * * 3、改 * 刚才Collection根接口没有提供修改的方法 * set(int index, E element) * * 4、查 * int indexOf(Object o) :从前往后 * int lastIndexOf(Object o ):从后往前 * get(int index) :返回index位置的元素 * subList(int fromIndex, int toIndex) :截取\[fromIndex,toIndex) * * 5、遍历 * (1)toArray * (2)foreach * (3)Iterator * (4)ListIterator * ListIterator是Iterator的子接口,Iterator有的,ListIterator也有,还增加了: * A:Iterator只能从前往后遍历 * ListIterator可以从任意位置开始,从前往后,或从后往前遍历 * * ListIterator的使用步骤: * 第一步:先获取ListIterator的对象 * 集合对象.listIterator() * 第二步:通过遍历方法 * hasNext()+next() * hasPrevious() + previous() * B:不仅可以在遍历是删除了,还增加了set和add方法。 * \*/ public class TestList { @SuppressWarnings("all") @Test public void test5(){ List list = new ArrayList(); list.add("张三"); list.add("李四"); list.add("王五"); list.add("赵六"); list.add("前提"); list.add("王八"); //从前往后 ListIterator listIterator = list.listIterator();//默认迭代器指向最前面 while(listIterator.hasNext()){ Object next = listIterator.next(); System.out.println(next); } System.out.println(); //从最后往前 listIterator = list.listIterator(list.size());//要让迭代器先指到最后 while(listIterator.hasPrevious()){ Object previous = listIterator.previous(); System.out.println(previous); } System.out.println(); //从任意位置开始遍历 listIterator = list.listIterator(3);//要让迭代器先指到某个位置 while(listIterator.hasPrevious()){ Object previous = listIterator.previous(); System.out.println(previous); } } @SuppressWarnings("all") @Test public void test4(){ List list = new ArrayList(); list.add("张三"); list.add("李四"); list.add("王五"); int index = list.indexOf("张三"); System.out.println(index); Object object = list.get(2); System.out.println(object); } @SuppressWarnings("all") @Test public void test3(){ List list = new ArrayList(); list.add("张三"); list.add("李四"); list.add("王五"); list.set(0, "曹阳"); for (Object object : list) { System.out.println(object); } } @SuppressWarnings("all") @Test public void test2(){ List list = new ArrayList(); list.add("张三"); list.add("李四"); list.add("王五"); list.remove(0); for (Object object : list) { System.out.println(object); } } @SuppressWarnings("all") @Test public void test1(){ List list = new ArrayList(); list.add("张三"); list.add(0, "李四"); for (Object object : list) { System.out.println(object); } } } /\* * List的常见的实现类: * 1、Vector:动态数组 * 内部实现:数组,初始化大小为10 * 2、ArrayList:动态数组 * 内部实现:数组,初始化大小为10 * 3、LinkedList:双向链表、双端队列 * LinkedList实现了List、Queue、Deque接口 * 内部实现:链表 * 4、Stack:栈,又是Vector的子类 * 内部实现:数组 * * Stack:后进先出(LIFO)(Last in First out)、先进后出(FILO)(First in Last out) * 压栈:push,弹栈:pop(移除栈顶元素),peek(返回栈顶元素,但不移除) * 队列(Queue):先进先出(FIFO) * 添加到队列offer(e),移出队列,poll(),返回队头不移除peek() * 双端队列(Deque)(Double ended queue):队头和队尾都可以添加元素和移除元素 * offerFirst(e)、offerLast(e) * pollFirst()、pollLast() * peekFirst()、peekLast() * * 面试题:Vector与ArrayList有什么区别? * Vector:旧版,线程安全的,扩容为原来的2倍,支持迭代的方式更多,支持旧版Enumeration迭代器 * ArrayList:新版,线程不安全,扩容为原来的1.5倍,不支持老版的Enumeration迭代器 * * 面试题:动态数组和LinkedList有什么区别? * (1)内部实现不同: * 动态数组底层数组 * LinkedList是链表,元素的类型是节点类型,Node(prev,data,next) * (2)动态数组:对索引的相关操作,效率很高 * 链表:对索引的相关操作,效率比较低 * (3)动态数组:插入、删除,涉及到移动元素 * 链表 :插入,删除,只涉及到前后的元素的关系 * * 结论:如果是后面的操作针对索引更多,那么选择动态数组,如果是添加和删除,插入等操作更多,选择链表 \*/ # map # * java.util.Map:接口 * 和Collection最大的不同,就是它存储“键值对,映射关系” * * 常用方法: * 1、添加 * put(key,value):一次添加一对映射关系 * putAll(Map map):一次添加多对映射关系 * 2、删除 * remove(Object key);根据key删除一对 * clear():清空 * * 3、修改 * 通过put可以替换value,只要key相同,就会替换 * * 4、查询 * (1)containsKey(Object key):判断某个key是否存在 * (2)containsValue(Object value):判断某个value是否存在 * (3)V get(Object key):根据key获取value * (4)boolean isEmpty() :是否为空 * * 5、获取映射关系,键值对数:int size() * * 6、遍历 * (1)Set keySet() * (2)Collection values() * (3)Set entrySet():由entry对象构成的set,因为key不重复,那么entry对象也不会重复 * Map的实现类们: * 1、HashMap:哈希表 * 2、Hashtable:哈希表 * 3、LinkedHashMap: * 它是HashMap的子类,比HashMap多维护了添加的顺序。 * 4、TreeMap:映射关系的顺序会按照key的“大小”顺序排列 * 要求:映射关系的key,必须支持排序,即实现java.lang.Comparable接口,或者单独为TreeMap指定定制比较器对象。 * 5、Properties: * (1)Properties是Hashtable的子类 * (2)Properties的key和value的类型是String * * 面试题:Hashtable与HashMap的区别 * Hashtable:最古老,线程安全的,它的key和value不允许为null * HashMap:相对新,线程不安全,它的key和value都允许为null * * 类同:StringBuffer与StringBuilder、Vector与ArrayList # set # * java.util.Set:接口,是Collection的子接口。 * (1)不支持重复 * (2)无序的(和添加顺序无关) * * Set没有增加方法,都是Collection接口的方法。 * * Set: * (1)HashSet:完全无序 * 如何保证两个元素不重复?依据元素的equals方法 * (2)TreeSet:大小顺序,和添加顺序无关 * 如何保证两个元素不重复?依据元素的“大小”顺序 * (3)LinkedHashSet:遍历时可以保证添加顺序,存储和添加顺序无关 * LinkedHashSet是HashSet的子类,但是它的元素比HashSet的元素要多维护一个添加的顺序。 * LinkedHashSet的效率就比HashSet低,每次添加,删除,要同时考虑顺序。 * LinkedHashSet和HashSet一样依据equals,决定是否重复。 * * 结论:如果既要元素不重复,又要按大小,选TreeSet * 如果既要元素不重复,又要保证添加顺序,选LinkedHashSet * 如果只是要元素不重复,选择HashSet 下面是一个例子 题目 1、声明一个Book类型,有编号、书名、作者、价格,销量 2、添加到一个集合中,要求不可重复,规定编号相同就认为是一本书 提示:HashSet 3、添加到一个集合中,要求不可重复,但是要求按照销量从高到低排序 提示:TreeSet 4、添加到一个集合中,要求不可重复,但是要求这次按照价格从低到高排序 提示:TreeSet 5、添加到一个集合中,要求不可重复,但是要求按照添加顺序显示 提示:LinkedHashSet book类 package day21.homework; import java.util.Comparator; import java.util.Objects; public class Book implements Comparable<Book> { /** * 1、声明一个Book类型,有编号、书名、作者、价格,销量 */ private int id; private String bookName; private String author; private double price ; private int counts; @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Book book = (Book) o; return id == book.id; } @Override public int hashCode() { return Objects.hash(id); } public Book() { } public Book(int id, String bookName, String author, double price, int counts) { this.id = id; this.bookName = bookName; this.author = author; this.price = price; this.counts = counts; } @java.lang.Override public java.lang.String toString() { return "Book{" + "id=" + id + ", bookName='" + bookName + '\'' + ", author='" + author + '\'' + ", price=" + price + ", counts=" + counts + '}'; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getBookName() { return bookName; } public void setBookName(String bookName) { this.bookName = bookName; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public int getCounts() { return counts; } public void setCounts(int counts) { this.counts = counts; } @Override public int compareTo(Book o) { return o.counts-this.counts; } } Hashset package day21.homework; import java.util.HashMap; import java.util.HashSet; public class HashSetTest { //添加到一个集合中,要求不可重复,规定编号相同就认为是1本书 // 提示:HashSet public static void main(String[] args) { HashSet<Book> lists = new HashSet<>(); lists.add(new Book(1,"天龙八部","金庸",18,120)); lists.add(new Book(3,"倚天屠龙记","金庸",20,130)); lists.add(new Book(2,"火影忍者","mmm",22,222)); lists.add(new Book(1,"天龙八部1","金庸",18,120)); for (Book list : lists) { System.out.println(list); } } } Linkedhashset package day21.homework; import java.util.LinkedHashSet; public class LinkedHashSetTest { //添加到一个集合中,要求不可重复,但是要求按照添加顺序显示 // 提示:LinkedHashSet public static void main(String[] args) { LinkedHashSet<Book> lists = new LinkedHashSet<>(); lists.add(new Book(1,"天龙八部","金庸",18,120)); lists.add(new Book(3,"倚天屠龙记","金庸",20,130)); lists.add(new Book(2,"火影忍者","mmm",22,222)); lists.add(new Book(1,"天龙八部","金庸",18,120)); for (Book list : lists) { System.out.println(list); } } } Treeset package day21.homework; import java.util.Comparator; import java.util.TreeSet; public class TestSetTest01 { /** * 4、添加到一个集合中,要求不可重复,但是要求这次按照价格从低到高排序 * 提示:TreeSet * * 因为在上一题中,默认实现按照销量从高到低,我们就不方便再次修改Book类的compareTo方法 * 说明,Book类的自然排序规则,无法满足本题的要求。 * * 要求:给TreeSet对象要多传一个“定制比较器对象”,即java.util.Comparator * * Arrays.sort(arr):按照元素的自然排序 * Arrays.sort(arr,定制比较器对象) * * TreeSet set = new TreeSet();按照元素的自然排序 * TreeSet set = new TreeSet(定制比较器对象);按照定制比较器排序 * @param args */ public static void main(String[] args) { TreeSet<Book> lists = new TreeSet<>(new Comparator<Book>() { @Override public int compare(Book o1, Book o2) { return Double.compare(o1.getPrice(),o2.getPrice()); } }); lists.add(new Book(1,"天龙八部","金庸",18,120)); lists.add(new Book(3,"倚天屠龙记","金庸",20,130)); lists.add(new Book(2,"火影忍者","mmm",22,222)); lists.add(new Book(1,"天龙八部","金庸",18,120)); for (Book list : lists) { System.out.println(list); } } } Treeset01 package day21.homework; import java.util.TreeSet; public class TreeSetTest { public static void main(String[] args) { //添加到一个集合中,要求不可重复,但是要求按照销量从高到低排序 // 提示:TreeSet TreeSet<Book> lists = new TreeSet<>(); lists.add(new Book(1,"天龙八部","金庸",18,120)); lists.add(new Book(3,"倚天屠龙记","金庸",20,130)); lists.add(new Book(2,"火影忍者","mmm",22,222)); lists.add(new Book(1,"天龙八部","金庸",18,120)); for (Book list : lists) { System.out.println(list); } } }
还没有评论,来说两句吧...