集合笔记

集合

1. 概念

集合和数组一样用于保存多个数据,集合是通过算法实习的一种容器,数组是编程语言内置的容器,数组的元素个数是固定的,集合的长度是随着元素的增长而增长。集合提供了大量的api简化了编程的复杂度。

数据结构: 常见的如: 数组、链表、堆、栈、树、图

这些数据结构和编程语言无关。不同的编程语言可以通过算法逻辑实现这些数据结构。

2. 集合体系

在这里插入图片描述

  • Collection : 集合跟接口,他抽取了了集合的最基本操作
  • List : Collection 的子接口,扩展了有序集合的规范,支持下标访问操作,支持可重复元素
  • Set: Collection 的子接口,基本上没有做扩展,它是无序接口的规范,不支持接口的规范,不支持下标,元素不可重复。
3.Collection 接口方法
boolean add(E e) 
确保此集合包含指定的元素(可选操作)。  

boolean addAll(Collection<? extends E> c) 
将指定集合中的所有元素添加到此集合(可选操作)。 

void clear() 
从此集合中删除所有元素(可选操作)。  

boolean contains(Object o) 
如果此集合包含指定的元素,则返回 trueboolean containsAll(Collection<?> c) 
如果此集合包含指定 集合中的所有元素,则返回trueboolean isEmpty() 
如果此集合不包含元素,则返回 true 。

Iterator<E> iterator() 
返回此集合中的元素的迭代器。  
 
boolean remove(Object o) 
从该集合中删除指定元素的单个实例(如果存在)(可选操作)。

boolean removeAll(Collection<?> c) 
删除指定集合中包含的所有此集合的元素(可选操作)。  

boolean retainAll(Collection<?> c) 
仅保留此集合中包含在指定集合中的元素(可选操作)。  

int size() 
返回此集合中的元素数。  

Object[] toArray() 
返回一个包含此集合中所有元素的数组。  
4.List接口方法
void add(int index, E element) 
将指定的元素插入此列表中的指定位置(可选操作)。  

boolean addAll(int index, Collection<? extends E> c) 
将指定集合中的所有元素插入到此列表中的指定位置(可选操作)。  


E get(int index) 
返回此列表中指定位置的元素。  

int indexOf(Object o) 
返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1int lastIndexOf(Object o) 
返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1。  


E remove(int index) 
删除该列表中指定位置的元素(可选操作)。  


E set(int index, E element) 
用指定的元素(可选操作)替换此列表中指定位置的元素。  

List<E> subList(int fromIndex, int toIndex) 
返回此列表中指定的 fromIndex (含)和 toIndex之间的视图。  
5.Set接口

api 几乎和Collection 一致。

6.有序集合实现类
ArrayList :
  特点: 查询效率高,增删效率低 ,线程不安全。
  原理: 底层数组实现
  jdk1.2 新增
  
Vector :
  特点: 查询效率高,增删效率低 ,线程安全。
  原理: 底层数组实现
  jdk1.0 新增
  
LinkedList:
  特点: 查询效率低,增删效率高 ,线程不安全。
  原理: 底层链表实现
  jdk1.0 新增 
7.泛型
  • 类型参数化的一种机制,使用时在指定类型,可以提高代码的复用性、通用性,一般用于封装通用工具。
  • java集合中都支持泛型
  • 泛型可以定义:泛型类、泛型接口、泛型方法、 泛型参数

示例:

定义泛型类:
public class AAA<T>{
   //内部可以使用T 当做数据类型做一切类型可做的事情
}

定义接口:
public interface AAA<T>{
   //内部可以使用T 当做数据类型做一切类型可做的事情
}

定义泛型方法
public class AAA{
    public  <T>  T  method(T t){
    //
    }
}
泛型限定:
public void  method(List<String>  args  ){  // 指定类型集合的参数
}
public void  method(List<?>  args  ){      //  任意类型的泛型集合
}
public void  method(List<? extends Number>  args  ){ // 指定 Number 及其子类的泛型集合
}
public void method(List< ? super Integer > args){ //   指定 Number 及其父类的泛型集合
}

基本数据类型不支持泛型,可以使用包装类代替

8.Collection集合工具类
提供了集合操作的一些方法。
public static void main(String[] args) {		
		List<String> list = new LinkedList();
			
		list.add("ABCD");
		list.add("ABCE");
		list.add("ABCF");
		list.add("ABCG");
		
		//1.反转
		Collections.reverse(list);	
		System.out.println(list);
		
		//2.打乱
		Collections.shuffle(list);
		System.out.println(list);
		
		//4.排序
		List<Integer> nums = new Vector<Integer>();
		nums.add(12);
		nums.add(1);
		nums.add(120);
		nums.add(44);
		Collections.sort(nums);
		System.out.println(nums);		
}
9.Set实现类

HashSet:底层使用HashMap,利用Map的key来保存元素

去重原理:添加时先判断hashcode时后一致,不一致直接保存,一致进一步判断equals(可重写,定义自己的相等规则),相等是为重复,放弃存储,若不同则存放

自定义类型去重重写 Hashcode 和 equals

LinkedHashSet:底层LinkedHashSet来实现,可以记录元素插入顺序

TreeSet: 底层使用TreeMap实现,可以对元素排序

  1. 排序方案: 元素类型 实现Comparetor接口重写CompareTo(T 0)
  2. 构造器传入 Comparetor 对象 重写 Compare(T o1,T o2);

对于List排序可以使用Collections.sort(List list,Comparator cpr)

10.迭代器

全体集合都可以获得迭代器通过 iterator(): iterator

iterator接口提供了两个方法

  1. hasNext(): boolean 判断集合中是否还有可获取元素
  2. next(): 获得当前元素
Iterator<String> it = arr.iterator();
//判断是否还有可获取的元素
while( it.hasNext()  ) {
    String s= it.next();
    System.out.println(s);
}

迭代器原理:

public E next() {
    checkForComodification();
    int i = cursor;
    if (i >= size)
        throw new NoSuchElementException();
    Object[] elementData = ArrayList.this.elementData;
    if (i >= elementData.length)
        throw new ConcurrentModificationException();
    cursor = i + 1;
    return (E) elementData[lastRet = i];
}

调用next方法底层就是操作数组的下标,并返回元素

11.Map实现类

map集合主要是保存一种映射关系,键对值的关系。常见非法:

clear() 
从该地图中删除所有的映射(可选操作)。  
 
boolean containsKey(Object key) 
如果此映射包含指定键的映射,则返回 trueboolean containsValue(Object value) 
如果此地图将一个或多个键映射到指定的值,则返回 true 。 

Set<Map.Entry<K,V>> entrySet() 
返回此地图中包含的映射的Set视图。  
   
V get(Object key) 
返回到指定键所映射的值,或 null如果此映射包含该键的映射。  
 
boolean isEmpty() 
如果此地图不包含键值映射,则返回 true 。  

Set<K> keySet() 
返回此地图中包含的键的Set视图。  
  
V put(K key, V value) 
将指定的值与该映射中的指定键相关联(可选操作)。  
void putAll(Map<? extends K,? extends V> m) 
   
V remove(Object key) 
如果存在(从可选的操作),从该地图中删除一个键的映射。  
 
int size() 
返回此地图中键值映射的数量。 

Collection<V> values() 
返回此地图中包含的值的Collection视图。  
12 HashMap

HashMap: 底层通过哈希表(数组加链表)实现,线程不安全,执行下O效率高。
在jdk8中引入红黑树,如果链表长度超过8则转成树,提高查询效率。
存值原理:

添加元素方法:
public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
}

计算hash值方法:
static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

存值流程:
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i;
        if ((tab = table) == null || (n = tab.length) == 0)  // 判断数组是否需要初始化
            n = (tab = resize()).length; //resize() 初始化
    
        if ((p = tab[i = (n - 1) & hash]) == null) // 计算下标,判断位置处是否有元素 
            tab[i] = newNode(hash, key, value, null);//没有元素直接存
        else {
            Node<K,V> e; K k;
            // 如何key相同,把原来NOde记录下
            if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;
            
            // 如果此位置是一个树结构
            else if (p instanceof TreeNode)
                //添加到树结构中
                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
            
            // 如果此位置是一个链表则添加到链表末尾
            else {
                for (int binCount = 0; ; ++binCount) {
                    //查链表,把元素添加到链表末尾
                    if ((e = p.next) == null) {
                        p.next = newNode(hash, key, value, null);
                        //如果链表如果超过8 则把链表转成红黑树
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash);
                        break;
                    }
                    // 如果这元素与 链表上的元素相等, 结束遍历
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    //交换地址,继续搜索
                    p = e;
                }
            }
            
            // key 已经存在, 覆盖原来的值。
            if (e != null) { // existing mapping for key             // 保存旧值
                V oldValue = e.value;
                // 覆盖旧值
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                //返回旧值
                return oldValue;
            }
        }
       //操作数 ++
        ++modCount;
        //容量+1 如果操作临界值,则扩容。
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);
        return null;
    }

map便利

public class TestHashMap {

	public static void main(String[] args) {
		
		//实例化
		HashMap<String,String> map = new HashMap<>();
		
		
		//添加元素:
		map.put("swk", "孙悟空");
		map.put("zbj", "猪八戒");
		map.put("ts", "唐僧" );

		
		//获得元素个数: 键值对个数
		System.out.println(  map.size()  );
		
		
		//根据 key 获得 value
		String value =  map.get("swk");
		System.out.println(value);
		
		
		//移除跟进key
		map.remove("zbj");
	 
		
		//获得全部的 key
		System.out.println("----------------------");
		Set<String> keys = map.keySet();
		for(String k : keys ) {
			System.out.println(k);
		}
		
		//获得全部的 value
		System.out.println("-----------------------");
		Collection<String> values = map.values(); 
		for(String v : values) {
			System.out.println(v);
		}
		
		//map遍历方式:获得Entry集合 
		System.out.println("------------------------");
		Set<  Entry<String, String> > entrys = map.entrySet();
		for( Entry<String, String> entry : entrys ) {
			System.out.println( entry.getKey()+":"+entry.getValue() );
		}
		
		//map遍历方式:通过keySet集合 配合  get(key)
		System.out.println("-------------------------");
		for( String key  : map.keySet() ) {
			System.out.println( key+":"+ map.get(key)     );
		}
				
		//检测方法,时候为空集合
		System.out.println( map.isEmpty()  );
				
		System.out.println( map.containsKey("ts") );			
	    System.out.println(map.containsValue("孙悟空"));
			
  }
}
12. Hashtable

早期保存键值对的集合,底层也是使用哈希表算法实现,是Dictionary 字典类的子类,线程安全,执行效率低,不允许使用null键和null值

13. Properties

properties是Hashtable的子类,主要保存配置文件,键和值都是String,可以读取配置文件 ****.properties

	public static void main(String[] args) throws FileNotFoundException, IOException {
		
		//实例化集合
		Properties pro = new Properties();
		
		//手动添加键值对
		pro.put("abc", "hello");
		
		//通过IO流读取配置文件
		pro.load( new FileInputStream("src/map/config.properties")  );

        //遍历
	    for( Object key : pro.keySet() ) {
	    	
	        System.out.println(key+":"+ pro.get(key)  ); ;
	    	
	    }
	}

配置文件

ip=192.168.1.90
prot=8080
14.Treemap

可实现,对键进行排序,实际上TreeSet 底层使用的就是TreeMap (了解)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值