Day13-14:集合(Collection接口和Map接口)、Comparator接口、Collections工具类

一.集合

集合:Java API所提供的一系列类,可以用于动态存放多个对象。

           集合类全部支持泛型,是一种数据安全的用法。

            LinkedList<String>  list = new LinkedList<>();

集合与数组不同在于:
    1.集合是大小可变的序列,数组一旦声明长度不可变
    2.同一个集合可以存放多种数据类型,数组只能存放声明时指定的数据类型
    3.集合只能存储引用数据类型,数组可以存储基本数据类型及引用数据类型

另外还有三个分支,均是为上述两大家族服务的。

Iterator(迭代器)家族。主要用于遍历Colleciton接口的及其子类而设计。

Comparator(比较器), 在集合中存储对象时候,用于对象之间的比较

Collections是工具类。注意该类名带个s,一般就表示工具类。里面提供了N多静态方法,来对Colleciton集合进行操作。

 

二.Collection接口

该接口下的所有子孙类均存储的是单一对象。 Add(s)

Collection接口-定义了存取对象的方法。有两个非常常用的子接口:

List接口:存放的元素有序且允许有重复的集合接口。

Set接口:存放的元素无序不包含重复的集合接口。

说明:

“有序”-元素存入的顺序与取出的顺序相同.

“无序”—元素存入的顺序与取出的顺序不相同

(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的,加入Set 的Object必须定义equals()方法 ,另外list支持for循环,也就是通过下标来遍历,也可以用迭代器,但是set只能用迭代,因为他无序,无法用下标来取得想要的值。)

Collection接口中的常用方法

  1. int size();                                                            返回此collection中的元素数。
  2. boolean isEmpty();                                            判断此collection中是否为空。
  3. boolean contains(Object obj);                           判断此collection是否包含指定的元素。
  4. boolean contains(Collection c);                         判断此collection是否包含指定collection中的所有元素。
  5. boolean add(Object element);                           向此collection中添加元素。
  6. boolean addAll(Collection c);                             将指定collection中的所有元素添加到此collection中
  7. boolean remove(Object element);                      从此collection中移除指定的元素。
  8. boolean removeAll(Collection c);                      移除此collection中那些也包含在指定collection中的所有元素。
  9. void clear();                                                       移除些collection中所有的元素。
  10. boolean retainAll(Collection c);                         仅保留此collection中那些也包含在指定collection的元素。
  11. Iterator iterator();                                               返回在此collection的元素上进行迭代的迭代器。
  12. Object[] toArray();                                           把此collection转成数组。

 

1.List接口

(1)ArrayList

数据结构:一维数组

特点:有序、可重复,长度不固定,线程不安全,效率高。

优点:ArrayList是实现了基于动态数组的数据结构,因为地址连续,一旦数据存储好了,查询操作效率会比较高(在内存里是连着放的)。

缺点:因为地址连续, ArrayList要移动数据,所以插入和删除操作效率比较低。

应用场景:存储数据

public class Test01 {

	public static void main(String[] args) {
		
		//创建ArrayList对象
		ArrayList list = new ArrayList();
		
		//添加
		list.add("古川伊织");
		list.add("明日花");
		list.add("谢刚");
		list.add("麻生希");
		list.add(18);//默认自动装箱:Integer.valueOf(18);
		
		//获取元素
		System.out.println("获取指定下标上的元素:" + list.get(0));
		//获取个数
		System.out.println("获取集合中元素的个数:" + list.size());
		//查询、判断
		System.out.println("查询该集合是否没有元素:" + list.isEmpty());
		System.out.println("判断该集合是否有指定元素:" + list.contains("明日花"));
		System.out.println("查询该元素在集合中的下标:" + list.indexOf("谢刚"));
		
		//替换
		list.set(3, "爱田奈奈");
		
		//删除
		list.remove(2);//以下标删除
		list.remove("明日花");//以元素删除
		
		
		//遍历1:for循环
		for (int i = 0; i < list.size(); i++) {
			System.out.println(list.get(i));
		}
		System.out.println("---------------");
		
		//遍历2:foreach
		for (Object obj : list) {
			System.out.println(obj);
		}
		System.out.println("---------------");
		
		//遍历3:迭代器
		Iterator it = list.iterator();
		while(it.hasNext()){//判断是否有迭代的元素
			
			Object next = it.next();//获取元素
			System.out.println(next);
		}		
	}
}

输出:
获取指定下标上的元素:古川伊织
获取集合中元素的个数:5
查询该集合是否没有元素:false
判断该集合是否有指定元素:true
查询该元素在集合中的下标:2
古川伊织
爱田奈奈
18
---------------
古川伊织
爱田奈奈
18
---------------
古川伊织
爱田奈奈
18

(2)LinkedList

数据结构:双向链表

特点:有序、可重复。

优点:LinkedList基于链表的数据结构,地址是任意的,所以在开辟内存空间的时候不需要等一个连续的地址,对于新增和删除操作add和remove,LinedList比较占优势。LinkedList 适用于要头尾操作或插入指定位置的场景

缺点:因为LinkedList要移动指针,所以查询操作性能比较低。

适用场景分析:
当需要对数据进行对此访问的情况下选用ArrayList,当需要对数据进行多次增加删除修改时采用LinkedList。

应用场景:存储数据、栈模式(removeLast)、队列模式(removeFirst)

public class Test01 {
	public static void main(String[] args) {
		LinkedList<String> list = new LinkedList<>();
		list.add("A");
		list.add("B");
		list.add("C");
		list.add("D");
		//删除
		list.remove(2);//以下标删除
		list.remove("D");//以元素内容删除
		//查询
		System.out.println("查询该元素在集合中的下标:"+list.indexOf("A"));
		System.out.println("查询集合是否为空:"+list.isEmpty());
		System.out.println("查询是否有该元素:"+list.contains("A"));
		
		//替换
		list.set(1, "b");
		//遍历1:迭代器遍历
		Iterator<String> it = list.iterator();
		while(it.hasNext()) {//判断是否有迭代的元素
			String next = it.next();//获取元素
			System.out.println(next);
		}
		System.out.println("集合中元素的个数为:"+list.size());
		
		//遍历2:for循环
		for(int i=0;i<list.size();i++) {
			System.out.println(list.get(i));
		}
		//遍历3:foreach(底层由迭代器实现)
		for(String str:list) {
			System.out.println(str);
		}
		
	}
}
输出:
查询该元素在集合中的下标:0
查询集合是否为空:false
查询是否有该元素:true
A
b
集合中元素的个数为:2
A
b
A
b
public class Test03 {
	public static void main(String[] args) {
		//栈模式:先进后出
		LinkedList<String> list =new LinkedList<>();
		list.add("元素1");
		list.add("元素2");
		list.add("元素3");
		list.add("元素4");
		
		//遍历
		while(!list.isEmpty()) {
			String string = list.removeLast();//删除并返回最后一个元素
			System.out.println(string);
		}
		System.out.println(list.size());
	}
}
输出:
元素4
元素3
元素2
元素1
0
import java.util.LinkedList;

public class Test04 {
	public static void main(String[] args) {
		//队列模式:先进先出
		LinkedList<String> list =new LinkedList<>();
		list.add("元素1");
		list.add("元素2");
		list.add("元素3");
		list.add("元素4");
		
		//遍历
		while(!list.isEmpty()) {
			String string = list.removeFirst();//删除并返回第一个元素
			System.out.println(string);
		}
		System.out.println(list.size());
		
	}
}
输出:
元素1
元素2
元素3
元素4
0

ArrayList 与 LinkedList的区别:
    1.ArrayList与LinkedList实现了List接口,所以基本使用完全相同
    2.LinkedList有队列模式和栈模式的方法,分别是:removeFrist、removeLast
    3.效率问题:
        添加元素:ArrayList(不扩容的情况下快)
        删除元素:LinkedList快
        插入元素:LinkedList快
        修改元素:ArrayList快
        查询元素:ArrayList快
    经验:在工作中,这两个集合,ArrayList会用的多一点,因为增删查改的功能中查询的功能最常用,如果使用队列模式或者栈模式就是用LinkedList

(3)Vector

数据结构:一维数组

特点:有序可重复,线程安全

Vector类中的方法很多有synchronized进行修饰,是多线程安全的,线程安全就是说多线程访问同一代码,不会产生不确定的结果。而ArrayList不是,这个可以从源码中看出,,这样就导致了Vector在效率上无法与ArrayList相比;

两个都是采用的线性连续空间存储元素,但是当空间不足的时候,两个类的增加方式是不同。
Vector可以设置增长因子,而ArrayList不可以。

Vector是一种老的动态数组,是线程同步的,效率很低,一般不赞成使用。
适用场景分析:
Vector是线程同步的,所以它也是线程安全的,而ArrayList是线程异步的,是不安全的。如果不考虑到线程的安全因素,一般用ArrayList效率比较高。如果集合中的元素的数目大于目前集合数组的长度时,在集合中使用数据量比较大的数据,用Vector有一定的优势。

应用场景:存储数据、线程安全

public class Test01 {
	public static void main(String[] args) {
		Vector<String> vector = new Vector<>();
		vector.add("元素1");
		vector.add("元素2");
		vector.add("元素3");
		vector.add("元素4");
		
		vector.remove(2);
		Iterator<String> it = vector.iterator();
		while(it.hasNext()) {
			String next = it.next();
			System.out.println(next);
		}
	}
}
输出:
元素1
元素2
元素4
public class Test02 {
	public static void main(String[] args) {
		//Vector较老名称的方法
		Vector<String> vector = new Vector<>();
		vector.addElement("元素1");
		vector.addElement("元素2");
		vector.addElement("元素3");
		vector.addElement("元素4");
		
		vector.removeElement("元素2");//以内容删除
		vector.removeElementAt(1);//以下标删除
		vector.setElementAt("元素5", 0);//替换
		Enumeration<String> elements = vector.elements();
		while(elements.hasMoreElements()) {
			String nextElement = elements.nextElement();
			System.out.println(nextElement);
		}
	}
}
输出:
元素5
元素4

(4)Stock

数据结构:一维数组

特点:有序可重复,是Vector的子类

应用场景:存储数据、栈模式(push-放入,pop-拿出)

public class Test01 {
	public static void main(String[] args) {
		//Stack为栈模式
		Stack<String> stack = new Stack<>();
		//把元素压如栈顶
		stack.push("元素1");
		stack.push("元素2");
		stack.push("元素3");
		stack.push("元素4");
		
		//遍历
		while(!stack.isEmpty()) {
			String pop = stack.pop();
			System.out.println(pop);
		}
	}
}

 

2.set接口

set和list对比

  • Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。
  • List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。

set和map区别

  • List是对象集合,允许对象重复。
  • Map是键值对的集合,不允许key重复。

(1)HashSet

数据结构:hash数组

应用场景:去重复(单个值存储)

public class Test01 {
	public static void main(String[] args) {
		
		HashSet<String> set = new HashSet<>();
		//添加
		set.add("元素1");
		set.add("元素2");
		set.add("元素3");
		set.add("元素4");
		
		//以元素删除
		set.remove("元素2");
		//获取个数
		System.out.println("元素个数为:"+set.size());
		//查询、判断
		System.out.println("查询该集合是否没有元素"+set.isEmpty());
		System.out.println("判断该集合是否有指定元素"+set.contains("元素1"));
		
		System.out.println("----------------------------------------");
		//遍历1:foreach
		for(String str:set) {
			System.out.println(str);
		}
		System.out.println("----------------------------------------");
		//遍历2:Iterator遍
		Iterator<String> it = set.iterator();
		while(it.hasNext()) {
			String next = it.next();
			System.out.println(next);
		}
		
	}
}
输出:
元素个数为:3
查询该集合是否没有元素false
判断该集合是否有指定元素true
----------------------------------------
元素1
元素3
元素4
----------------------------------------
元素1
元素3
元素4
import java.util.HashSet;
import java.util.Iterator;

public class Test02 {
	public static void main(String[] args) {
		
		//证明HashSet无序且不可重复
		HashSet<Integer> set = new HashSet<>();
		//添加
		set.add(11);
		set.add(22);
		set.add(33);
		set.add(33);
		set.add(44);
		
		//遍历
		Iterator<Integer> it = set.iterator();
		while(it.hasNext()) {
			Integer next = it.next();
			System.out.println(next);
		}
	}
}
输出:
33
22
11
44

 

(2)TreeSet

数据结构:二叉树

String类型 字典排序

Integer类型 自然排序

public class Test01 {
	public static void main(String[] args) {
		//treeset基本使用
		TreeSet<String> set = new TreeSet<>();
		//添加
		set.add("a");
		set.add("b");
		set.add("c");
		set.add("d");
		
		//查询、判断
		System.out.println("查询集合中是否有该元素"+set.contains("a"));
		System.out.println("查询集合是否为空"+set.isEmpty());
		System.out.println("查询集合中元素个数"+set.size());
		
		//删除
		set.remove("a");
		//遍历1:foreach
		for(String string : set) {
			System.out.println(string);
		}
		System.out.println("------------");
		
		//遍历2:迭代器
		Iterator<String> it = set.iterator();
		while (it.hasNext()) {
			String string = (String) it.next();
			System.out.println(string);
		}
		
	}
}
输出:
查询集合中是否有该元素true
查询集合是否为空false
查询集合中元素个数4
b
c
d
------------
b
c
d

 

3.Map接口

该接口下的所有子孙均存储的是key-value(键值对)形式的数据。Put(key,value)

Map没有迭代器,不能直接遍历数据。

(1)HashMap

数据结构:hash数组

应用场景:Key去重复(键值对存储)

HashMap 的工作原理

 

  • Java中的HashMap是以键值对(key-value)的形式存储元素的。HashMap需要一个hash函数,它使用hashCode()和equals()方法来向集合/从集合添加和检索元素。
  • 当调用put()方法的时候,HashMap会计算key的hash值,然后把键值对存储在集合中合适的索引上。
  • 如果key已经存在了,value会被更新成新值。HashMap的一些重要的特性是它的容量(capacity),负载因子(load factor)和扩容极限(threshold resizing)。
  • HashMap是基于哈希表的Map接口的非同步实现,提供所有可选的映射操作,并允许使用null值和null键,不保证映射的顺序;HashMap是一个“链表散列”的数据结构,即数组和链表的结合体;它的底层就是一个数组结构,数组中的每一项又是一个链表,每当新建一个HashMap时,就会初始化一个数组;

HashSet 和 HashMap 区别

 

  • set是线性结构,set中的值不能重复,hashset是set的hash实现,hashset中值不能重复是用hashmap的key来实现的。
  • map是键值对映射,可以空键空值。HashMap是Map接口的hash实现,key的唯一性是通过key值hash值的唯一来确定,value值是则是链表结构。
  • 他们的共同点都是hash算法实现的唯一性,他们都不能持有基本类型,只能持有对象

  HashMap 和 Hashtable 的区别

  • 1.hashMap去掉了HashTable 的contains方法,但是加上了containsValue()和containsKey()方法。
  • 2.hashTable同步的,而HashMap是非同步的,效率上比hashTable要高。
  • 3.hashMap允许空键值,而hashTable不允许。
    注意:
    TreeMap:非线程安全基于红黑树实现。TreeMap没有调优选项,因为该树总处于平衡状态。
    Treemap:适用于按自然顺序或自定义顺序遍历键(key)。

遍历1:keySet():将map中的所有key获取出放在Set集合中,遍历set集合获取所有的key,就可以找到对应的value

遍历2:entrySet():将map中的所有映射关系获取出放在Set集合中,遍历set集合

public class Test01 {
	public static void main(String[] args) {
		
		//HashMap基本使用
		HashMap<String, Integer> map = new HashMap<>();
		//添加
		map.put("元素1", 1);
		map.put("元素2", 2);
		map.put("元素3", 3);
		map.put("元素4", 4);
		//获取
		System.out.println("获取value:"+map.get("元素1"));
		//获取个数
		System.out.println("查询集合中映射关系的个数:"+map.size());
		//查询、判断
		System.out.println("查询集合是否没有映射关系:"+map.isEmpty());
		System.out.println("查询是否有指定key:"+map.containsKey("元素2"));
		System.out.println("查询是否有指定value:"+map.containsValue(3));
		//通过key删除映射关系
		map.remove("元素1");
		
		//遍历1:keySet():将map中的所有key获取出放在Set集合中,遍历set集合获取所有的key,就可以找到对应的value
		Set<String> keySet = map.keySet();
		for(String key:keySet) {
			Integer value = map.get(key);
			System.out.println(key+"---------"+value);
		}
		System.out.println("---------------------------------------");
		
		//遍历2:entrySet():将map中的所有映射关系获取出放在Set集合中,遍历set集合
		Set<Entry<String, Integer>> entrySet = map.entrySet();
		for(Entry<String, Integer> entry:entrySet) {
			String key = entry.getKey();
			Integer value = entry.getValue();
			System.out.println(key+"---------"+value);
		}
		System.out.println("---------------------------------------");
	}
}
输出:
获取value:1
查询集合中映射关系的个数:4
查询集合是否没有映射关系:false
查询是否有指定key:true
查询是否有指定value:true
元素2---------2
元素3---------3
元素4---------4
---------------------------------------
元素2---------2
元素3---------3
元素4---------4
---------------------------------------
public class Test02 {
	public static void main(String[] args) {
		//HashMap特点:key不能重复,value可以重复
		
		HashMap<String, Integer> map = new HashMap<>();
		//添加
		map.put("元素1", 1);
		map.put("元素2", 2);
		map.put("元素3", 3);
		map.put("元素4", 4);
		
		//如果有相同key,就替换
		map.put("元素1",2);
		
		//value相同,不会替换
		map.put("元素5", 2);
	
		//输出
		Set<Entry<String,Integer>> entrySet = map.entrySet();
		for(Entry<String, Integer> entry:entrySet) {
			String key = entry.getKey();
			Integer value = entry.getValue();
			System.out.println(key+"-----------"+value);
		}	
	}
}
输出:
元素1-----------2
元素2-----------2
元素3-----------3
元素4-----------4
元素5-----------2
public class Test03 {
	public static void main(String[] args) {
		
		//获取字符换中字符出现的次数
		HashMap<Character, Integer> map = new HashMap<>();
		String str = "abcbcabacbacba11231221";
		char[] charArray = str.toCharArray();
		for(char s:charArray) {
			Integer value = map.get(s);
			if(value==null)
				map.put(s, 1);
			else
				map.put(s,value+1);
		}
		
		Set<Character> keySet = map.keySet();
		for(Character key:keySet) {
			Integer value = map.get(key);
			System.out.println("字符" + key + "出现次数为:" + value);
		}
	}
}
输出:
字符a出现次数为:5
字符1出现次数为:4
字符b出现次数为:5
字符2出现次数为:3
字符c出现次数为:4
字符3出现次数为:1


(2)ConcurrentHashMap

应用场景:多线程下key去重(键值对存储),效率高

ConcurrentHashMap 的工作原理

  • HashTable里使用的是synchronized关键字,这其实是对对象加锁,锁住的都是对象整体,当Hashtable的大小增加到一定的时候,性能会急剧下降,因为迭代时需要被锁定很长的时间。
  • ConcurrentHashMap算是对上述问题的优化,其构造函数如下,默认传入的是16,0.75,16
  • ConcurrentHashMap引入了分割(Segment),上面代码中的最后一行其实就可以理解为把一个大的Map拆分成N个小的HashTable,在put方法中,会根据hash(paramK.hashCode())来决定具体存放进哪个Segment,如果查看Segment的put操作,我们会发现内部使用的同步机制是基于lock操作的,这样就可以对Map的一部分(Segment)进行上锁,这样影响的只是将要放入同一个Segment的元素的put操作,保证同步的时候,锁住的不是整个Map(HashTable就是这么做的),相对于HashTable提高了多线程环境下的性能,因此HashTable已经被淘汰了。

HashMap 和 ConcurrentHashMap 的区别

  • ConcurrentHashMap是线程安全的HashMap的实现。
  • ConcurrentHashMap对整个数组进行了分割分段(Segment),然后在每一个分段上都用lock锁进行保护,相对于HashTable的syn关键字锁的粒度更精细了一些,并发性能更好,而HashMap没有锁机制,不是线程安全的。
  • HashMap的键值对允许有null,但是ConCurrentHashMap都不允许。
public class Test05 {

	public static void main(String[] args) {

		//ConcurrentHashMap基本使用

		ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

		//添加
		map.put("谢刚", 22);
		map.put("唐萌", 18);
		map.put("伍科", 30);
		map.put("李阳", 21);

		//获取
		System.out.println("通过指定key获取对应的value:" + map.get("唐萌"));
		//获取个数
		System.out.println("获取集合中映射关系的个数:" + map.size());
		//查询、判断
		System.out.println("查询该集合是否没有元素:" + map.isEmpty());
		System.out.println("判断该集合是否有指定key元素:" + map.containsKey("李阳"));
		System.out.println("判断该集合是否有指定value元素:" + map.containsValue(21));


		//删除:通过key删除映射关系
		map.remove("谢刚");

		//遍历1:keySet():将map中的所有key获取出放在Set集合中,遍历set集合获取所有的key,就可以找到对应的value
		Set<String> keySet = map.keySet();
		for (String key : keySet) {
			Integer value = map.get(key);
			System.out.println(key + " -- " + value);
		}
		System.out.println("----------------");

		//遍历2:entrySet():将map中的所有映射关系获取出放在Set集合中,遍历set集合
		Set<Entry<String, Integer>> entrySet = map.entrySet();
		for (Entry<String, Integer> entry : entrySet) {
			String key = entry.getKey();
			Integer value = entry.getValue();
			System.out.println(key + " -- " + value);
		}
	}
}
输出:
通过指定key获取对应的value:18
获取集合中映射关系的个数:4
查询该集合是否没有元素:false
判断该集合是否有指定key元素:true
判断该集合是否有指定value元素:true
唐萌 -- 18
李阳 -- 21
伍科 -- 30
----------------
唐萌 -- 18
李阳 -- 21
伍科 -- 30

 


(3)Hashtable

应用场景:多线程下key去重(键值对存储),效率低

public class Test04 {

	public static void main(String[] args) {

		//Hashtable基本使用

		Hashtable<String, Integer> map = new Hashtable<>();

		//添加
		map.put("谢刚", 22);
		map.put("唐萌", 18);
		map.put("伍科", 30);
		map.put("李阳", 21);

		//获取
		System.out.println("通过指定key获取对应的value:" + map.get("唐萌"));
		//获取个数
		System.out.println("获取集合中映射关系的个数:" + map.size());
		//查询、判断
		System.out.println("查询该集合是否没有元素:" + map.isEmpty());
		System.out.println("判断该集合是否有指定key元素:" + map.containsKey("李阳"));
		System.out.println("判断该集合是否有指定value元素:" + map.containsValue(21));


		//删除:通过key删除映射关系
		map.remove("谢刚");

		//遍历1:keySet():将map中的所有key获取出放在Set集合中,遍历set集合获取所有的key,就可以找到对应的value
		Set<String> keySet = map.keySet();
		for (String key : keySet) {
			Integer value = map.get(key);
			System.out.println(key + " -- " + value);
		}
		System.out.println("----------------");

		//遍历2:entrySet():将map中的所有映射关系获取出放在Set集合中,遍历set集合
		Set<Entry<String, Integer>> entrySet = map.entrySet();
		for (Entry<String, Integer> entry : entrySet) {
			String key = entry.getKey();
			Integer value = entry.getValue();
			System.out.println(key + " -- " + value);
		}
	}
}
输出:
通过指定key获取对应的value:18
获取集合中映射关系的个数:4
查询该集合是否没有元素:false
判断该集合是否有指定key元素:true
判断该集合是否有指定value元素:true
唐萌 -- 18
伍科 -- 30
李阳 -- 21
----------------
唐萌 -- 18
伍科 -- 30
李阳 -- 21

HashMap          vs            Hashtable          vs                ConcurrentHashMap
    共同点:基本运用一致
    区别1:
        HashMap:            允许null的key和value
        Hashtable:            不允许null的key和value
        ConcurrentHashMap:    不允许null的key和value
    区别2:
        HashMap:            线程不安全
        Hashtable:            线程安全(方法中加了synchronized同步锁)
        ConcurrentHashMap:    线程安全(分段式加锁,把ReentrantLock锁上在了Segment对象中,效率更高)

(4)TreeMap

数据结构:二叉树

特点:key的位置自然排序

public class Test01 {
	public static void main(String[] args) {
		//TreeMap基本使用
		TreeMap<String,Integer> map = new TreeMap<>();
		//添加
		map.put("a",1);
		map.put("b",2);
		map.put("c",3);
		map.put("d",4);
		
		//查询、判断
		System.out.println("查询集合中是否有该元素"+map.containsKey("a"));
		System.out.println("查询集合中是否有该元素"+map.containsValue(2));
		System.out.println("查询集合是否为空"+map.isEmpty());
		System.out.println("查询集合中元素个数"+map.size());
		
		//删除
		map.remove("a");
		//遍历1:keySet
		Set<String> keySet = map.keySet();
		for(String key:keySet) {
			Integer value = map.get(key);
			System.out.println(key+"--------------"+value);
		}
		System.out.println("------------------");
		
		//遍历2:entrySet
		Set<Entry<String,Integer>> entrySet = map.entrySet();
		for(Entry<String, Integer> entry:entrySet) {
			String key = entry.getKey();
			Integer value = entry.getValue();
			System.out.println(key+"--------------"+value);
		}
		
	}
}
输出:
查询集合中是否有该元素true
查询集合中是否有该元素true
查询集合是否为空false
查询集合中元素个数4
b--------------2
c--------------3
d--------------4
------------------
b--------------2
c--------------3
d--------------4

 

三、Comparator接口

Comparable接口 -- compareTo():类的对象要存入TreeSet中就必须实现此接口
Comparator接口 -- compare():在不能改动对象所属类的排序规则的情况下,在创建TreeSet时定义新的排序规则
优先级别:Comparator > Comparable

comparator 是javase中的接口,位于java.util包下,该接口抽象度极高,有必要掌握该接口的使用

大多数文章告诉大家comparator是用来排序,但我想说排序是comparator能实现的功能之一,他不仅限于排序

排序和分组的区别在于: 
排序时,两个对象比较的结果有三种:大于,等于,小于。 
分组时,两个对象比较的结果只有两种:等于(两个对象属于同一组),不等于(两个对象属于不同组)

 

学生类:实现了comparable接口,重写comparaTo

public class Student implements Comparable<Student>{

	private String name;	
	private int age;
	
	public Student() {}

	public Student(String name, int age) {
		super();
		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;
	}

	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}

	@Override
	/**
	 * return 返回负数 小于此对象  0 等于此对象  正数 大于此对象
	 */
	public int compareTo(Student o) {
		return this.age-o.age;
	}
	
	
}

面向用户类:Comparator通过匿名内部类实现

public class Test02 {
	public static void main(String[] args) {
		
		//匿名内部类、Comparator
		TreeSet<Student> set = new TreeSet<>(new Comparator<Student>() {

			@Override
			public int compare(Student o1, Student o2) {
				//姓名一样,年龄一样,返回1
				if(o1.getName().equals(o2.getName()) && o1.getAge()==o2.getAge())
					return 1;
				//姓名长度不一样
				if(o1.getName().length() !=o1.getName().length())
					return o1.getName().length()-o2.getName().length();
				//姓名长度一样,年龄不一样
				if(o1.getName().length()==o2.getName().length() && o1.getAge()!=o2.getAge())
					return o1.getAge()-o2.getAge();
				return 1;
			}
			
		});
		//添加
		set.add(new Student("A同学哈", 11));
		set.add(new Student("C同学哈1", 12));
		set.add(new Student("B同学哈哈", 13));
		set.add(new Student("B同学哈哈", 15));
		set.add(new Student("D同学哈哈哈", 14));
		
		//遍历,根据年龄排序
		for (Student student : set) {
			System.out.println(student);
		}
	}
}

输出

Student [name=A同学哈, age=11]
Student [name=C同学哈1, age=12]
Student [name=B同学哈哈, age=13]
Student [name=B同学哈哈, age=15]
Student [name=D同学哈哈哈, age=14]

 

四、Collections工具类

public class Test02 {

	public static void main(String[] args) {
		
		ArrayList<String> list = new ArrayList<>();
		
		//批量添加
		Collections.addAll(list, "bc","abcdef","cdb");
		
		//依据此集合中数据类型的排序规则排序
//		Collections.sort(list);
		
		//自定义排序规则
		Collections.sort(list, new Comparator<String>() {
			@Override
			public int compare(String o1, String o2) {
				return o1.length()-o2.length();
			}
		});
		

输出:
bc
cdb
abcdef

		//批量替换
	Collections.fill(list, "同学");
		
		for (String str : list) {
			System.out.println(str);
		}
		
		
	}
}

输出:
同学
同学
同学

 

 

线程安全(Thread-safe)的集合对象:

  • Vector 线程安全:
  • HashTable 线程安全:
  • ConcurrentHashMap 线程安全:
  • StringBuffer 线程安全:

非线程安全的集合对象:

  • ArrayList :
  • LinkedList:
  • HashMap:
  • HashSet:
  • TreeMap:
  • TreeSet:
  • StringBulider:

引用:

1.https://blog.csdn.net/qq_37017448/article/details/88871088


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值