Collection、list、map、set、comparable、comparator

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);
        }

    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值