Java学习笔记二十(集合框架与Collections工具类)

集合框架中的两大父接口: Collection 和 Map

Collection

Collection  -->  List  Set  Queue

List   -->   LinkedList  ArrayList  Vector

Set   -->   HashSet  TreeSet

Map  -->   HashMap  TreeMap

其中,List中的元素是有序且可以重复的,长度是size()-1,Set中的元素是无序(无序指的是输入顺序和输出顺序不同,但是每次的输出顺序是不变的)且不可以重复的,Queue的底层是一个特殊的线性表(先进先出原则)

ArrayList --  动态数组实现的List,查找操作时效率高(常用的方法已经在之前的博文中大致说了)。

LinkedList -- 链表实现的List,插入和删除操作效率高。

Vector -- 线程安全的,效率低,已经被淘汰了。

扫描二维码关注公众号,回复: 3122518 查看本文章

集合框架的类都重写了toString方法,使输出的不再是地址而是数组,如果自定义的类添加到集合类的对象中,需要重写toString方法,得到非地址的输出。

Queue

从一端进,从另一端出,只有支持保持这种存储方式的函数。一般使用LinkedList实现,效率高。

常用API:

     boolean offer(E  e)        //添加

     E  poll()                            //移除

     E  peek()                          //查找

     也有提供add、remove之类的方法。

Deque

双端队列,每一端都可以进,也可以出,当我们限制双端队列的一端不能进或者出时,即为栈。

import java.util.Deque;
import java.util.LinkedList;
public class TestDeque {
	public static void main(String[] args) {
		Deque<String> deque = new LinkedList<String>();
		deque.offer("a");                                  //加入元素
		deque.offer("b");
		deque.offerLast("c");                              //向末尾加入元素
		deque.offerFirst("d");                             //向头加入元素
		System.out.println(deque); 
		System.out.println(deque.pollFirst());             //取出头的元素
		System.out.println(deque);
		System.out.println(deque.pollLast());              //取出尾的元素
		System.out.println(deque);
		System.out.println(deque.peekFirst());             //查看头的元素
		System.out.println(deque.peekLast());              //查看尾的元素
	}
}

Set

无序(元素没有下标的概念)、遍历时的顺序和添加时的顺序不一致。常用实现类:HashSet、LinkedHashSet、TreesSet

元素不能重复:是指调用equals方法相等,即内容相等。可以添加null元素。

在向Hashset中添加元素时,调用的add方法是计算两个对象的hash值是否相等来判断的。

其中较重要的实现类

HashSet

       当Set集合中已经存在大量元素,查找Set中是否有重复元素会耗费大量的时间,为节省时间,采用Hash函数来减少时间。

       HashSet的底层是HashMap加上操作,作为Map中的key存储。

       Hash函数原理: 调用HashCode方法,返回一个int型数据。Set集合在存入第一个元素时,先计算第一个元素的HashCode值,放到该返回值相应的存储空间里。如果两个不同的数返回的HashCode值是相同的,则在这个HashCode后形成一个链表来存放数据(尽量避免使用链表,因为会降低查找速度,即尽量让数据的HashCode值都不同)。

       所以在实现HashSet时,都会重写HashCode方法,让类中的每个属性都参与计算,尽量让集合中的对象的HashCode值都不同。同样,也需要重写equals,不然可能会发生Set中放入了两个相同元素的情况。(在equals中比较了哪些性质,在hashCode中让这些性质参与计算即可)

       可得出结论: HashCode相同,equals不一定相同

                            HashCode不同,equals一定不同

       需要特别注意的是: 对象添加到Set后,不能改变其属性。因为属性改变后,其HashCode也会改变,再根据新产生的HashCode值寻找对象的话,将无法找到,也会导致更改之前的对象不会被找到,也无法被删除清理,积累多了会造成内存溢出(在删除时,需要将集合中的对象取出后计算其HashCode再根据hash值找到元素再删除该位置的元素,改变后的元素其HashCode与存入时不一样,则会删除新值对应的位置,会造成内存溢出,而旧值对应的则一直存在原处)。在遍历时,只是把集合中的所有元素取出来,不涉及计算hash值,则没有问题。

        如果想删除地址信息不知道的对象时,就创建一个和它内容完全相同的对象,比较集合中是否有HashCode与之相同的。例如set.remove(new Student("毛毛",1)。

LinkedHashSet  

         使用hash算法来存储元素,但是使用链表维护次序,输入是按插入顺序的。

TreeSet

         使用二叉树维护元素的次序,输出次序是二叉树的中根遍历。是自然序输出的。

LinkedHashSet与HashSet比较:

         在插入元素性能上,HashSet性能高

         在遍历元素性能上,LinkedHashSet性能高

Collections

Collections是集合框架的工具类,提供了对List、Set、Map的操作,如排序、查找、修改等。

之前的文章说过了Collections.sort的相关方法,除此之外还有很多常用API:

      reverse(Collection)                   //集合反转,没有返回值

      shuffle(Collection)                     //对集合进行随机排序(混洗)

      swap(Collection,int,int)              //交换两个int代表的索引位元素

      Object max(Collection)             //返回集合中的最大值(也有相同的min方法)

      Object max(Collection,Comparator)      //返回接口定义的规则找到最大的

      int frequency(Collection,Object)          //返回Object对象出现的次数

      replaceAll(List list,Object old,Object new)    //替换集合中的全部old元素为new元素

Map

       是集合框架中的一个独立的映射接口,用于保存具有映射关系的数据,以key-value键值对来保存数据的,没有顺序。

       特点:(1)作为key的对象是不能重复的

                 (2)key可以为null

                 (3)key和value必须是单向的一对一的映射关系

                 (4)key和value都必须是引用类型的对象

       对map的遍历:

                 (1)entrySet方法(将每一个key-value封装成一个entry)

                 (2)  keySet方法(将所有的key放在一个新的Set里)

                 (3)  values方法(将所有的value放在一个新的set里)

       map的底层: 用数组和链表来存储数据,数组是hash表,通过map的key的hashcode返回值来定位,数组的每一个元素对应一个单向链表。

       常用的实现类:

HashMap

        使用了hash算法存储key-value键值对,key是无序的,value可以重复。key对象需要重写equals和hashcode方法。

        线程不安全,效率高。

        常用方法:

import java.util.HashMap;
import java.util.Map;
public class TestMap {
	public static void main(String[] args) {
		Map<String,String> map =new HashMap<String,String>();
		/*
		 * put(E key,E value)
		 * 存入一对key-value
		 * 如果key在map上出现过,那么会覆盖原来的key-value
		 */
		map.put("毛毛", "90");
		map.put("毛一", "90");
		map.put("毛二", "89");
		/*
		 * 输出格式; {key=value,key=value...}
		 */
		System.out.println(map);
		/*
		 * key重复时 替换原值 (如果是覆盖添加,返回原value)
		 */
		map.put("毛毛", "91"); 
		System.out.println(map);
		/*
		 * 能否添加null为key?
		 */
		map.put(null,"20");
		System.out.println(map);
		/*
		 * containsKey(Object obj)
		 * 查看map中是否包含某个key
		 */
		System.out.println(map.containsKey("毛毛"));
		System.out.println(map.containsValue("90"));
		/*
		 * 清空key-value
		 */
		map.clear();
		System.out.println(map);
	}
}
import java.util.HashMap;
import java.util.Map;
public class TestMap1 {
	public static void main(String[] args) {
		Map<String,Double> map =new HashMap<String,Double>();
		map.put("毛毛",10.0);
		map.put("毛一",100.0);
		map.put("毛二", 20.0);
		/*
		 * V remove(Object obj)
		 * 移除map中的一个key-value 返回value数据
		 * 如果key不存在 返回值为null
		 */
		System.out.println(map.remove("毛一"));
		/*
		 * V get(Object key)
		 * 如果没有此key,返回null
		 */
		System.out.println(map.get("毛毛"));
	}
}
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class TestMap2 {
	public static void main(String[] args) {
		Map<String,Double> map =new HashMap<String,Double>();
		map.put("毛毛",10.0);
		map.put("毛一",100.0);
		map.put("毛二", 20.0);
		/*
		 * Set<Entry<K,V>> entrySet()
		 * 返回值为set集合 
		 * 集合里封装的是每一对的key-value的Entry对象
		 * 
		 * Entry是Map的内部类 
		 * Entry对象封装了一对key-value
		 */
		Set<Entry<String,Double>> set = map.entrySet();
		/*
		 * 增强for循环,也叫for-each,即遍历
		 */
		for(Entry<String,Double> a:set) {
			System.out.println(a);
			/*
			 * Entry内部类的方法getKey getValue
			 */
			System.out.println(a.getKey());
			System.out.println(a.getValue());
		}
		/*
		 * Set<K> keySet()
		 * 返回map中所有的key 封装成一个set集合
		 */
		Set<String> keys = map.keySet();
		for(String key:keys) {
			Double b = map.get(key);
			System.out.println(key+"--"+b);
		}
		/*
		 * Collection<V> values()
		 * 获取map中所有的value封装成Collection对象
		 */
		Collection<Double> col= map.values();
		for(Double d:col)
			System.out.println(d);
		}

}

TreeMap

       底层使用二叉树维护key-value的次序,可以使用自定义排序和自然排序(即放入key的对象要实现Comparable接口),TreeSet也是。

HashTable

          比较古老,线程安全,效率低,key和value都不能使用null。

LinkedHashMap

          底层使用链表来维护次序。

Properties

          也是以key-value作为键值对存储信息,不需要加泛型,父类型是HashTable。

猜你喜欢

转载自blog.csdn.net/weixin_40373090/article/details/80791484