集合框架

Collection(接口)

常用方法(也就是后面都有的)

注: 可能返回值有的不同 但大致一样

boolean add(E e);		//添加
boolean remove(E e);	//删除
void clear();			//清空集合
boolean contains(E e);  //判断集合中是否包含某个元素
boolean isEmpty();		//判断集合是否为空
int size();				//获取长度
Object[] toArray();		//将集合转换成数组

Iterator(接口 迭代器)

通用取出集合中元素的方式

  • 迭代:即Collection集合元素的通用获取方式。在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续再判断,如果还有就再取出来。一直把集合中的所有元素全部取出。

常用方法

  • public E next();返回迭代的下一个元素
  • public boolean hasNext(); 如果还有元素可以迭代,则返回true
public class demo {
    public static void main(String[] args) {
        Collection<String> coll = new ArrayList<>();
        coll.add("1");
        coll.add("2");
        coll.add("3");
        coll.add("4");
        coll.add("5");

        //多态   接口             实现类对象
        Iterator<String> it = coll.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }
    }
}

Collections集合工具类的方法

public static <T> boolean addAll (Collection<T> c,T...elements);往集合中添加一些元素。
public static void shuffle(List<?> list) ;打乱顺序:打乱集合顺序。

public static void main(String[] args){
	ArrayList<String> list = new ArrayList<>();
	//添加多个元素
	list.add("a"); 
	list.add("b"); 
	list.add("c"); 

	Collections.addAll(list, "a", "b", "c");//和上面添加一样的效果
	Collections.shuffle(list);//打乱list集合

}

public static <T> void sort(List<T> list) ; 将集合中元素按照默认规则(升序)排序。

public static void main(String[] args){
	ArrayList<Integer> list01 = new ArrayList<>();
	list01.add(1);
	list01.add(3);
	list01.add(2);
	System.out.println(list01);//输出为 [1, 3, 2]

	Collections.sort(list01);//输出为 [1, 2, 3]

/*==============================================================*/
	//假设有一个 有名字和年龄属性的Person类
	ArrayList<Person> list02 = new ArrayList<>();
	list02.add(new Person("A", 18));
	list02.add(new Person("B", 12));
	list02.add(new Person("C", 23));
	System.out.println(list02);//输出一般自动重写为 [Person{name="A", age=18}, Person{name="B", age=12}, Person{name="C", age=23}]

//	Collections.sort(list02);//直接的话 编译不通过  得先实现接口
// 注意:
//		sort(List<T> list )使用前提
//		被排序的集合里边存储的元素,必须实现Comparable,重写接口中的方法compareTo定义排序的规则
//	所以 我们的Person类必须实现Comparable接口 并重写compareTo方法  如下
}
class Person implements Comparable<Person>{
	public int compareTo({Person o){
		//return 0;//认为元素都是相同的
		//自定义比较规则,比较两人的年龄(this,参数Person)
		return this.getAge() - o.getAge();//年龄升序 反过来降序
	}
}

public static <T> void sort(List<T> list ,Comparator<? super T> ) ; 将集合中元素按照指定规则排序。

public static void mian(String[] args){
	ArrayList<Person> list = new ArrayList<>();
	list.add(new Person("A", 18));
	list.add(new Person("B", 12));
	list.add(new Person("aC", 23));
	list.add(new Person("bC", 23));

	 Collections.sort(list, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
            	//按年龄升序排序
                int result = o1.getAge() - o2.getAge();
                //如果年龄一样 按名字排序
                if (result == 0){
                	result = o1.getName().charAt(0) - o2.getName().charAt(0);
                }
                return result;
            }
        });
        System.out.println(list);//[0, 1, 2, 3]

}

大致小结

public class demo05工具类 {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
//1. public static <T> boolean addAll (Collection<T>  c,T...elements);往集合中添加一些元素。
        Collections.addAll(list,1,3,2,0);
        System.out.println(list);//[1, 3, 2, 0]
//2. public static void shuffle(List<?> list);打乱顺序:打乱集合顺序。
        Collections.shuffle(list);
        System.out.println(list);//乱排序
//3. public static <T> void sort(List<T> list);  将集合中元素按照默认规则(升序)排序。
        Collections.sort(list);
        System.out.println(list);//[0, 1, 2, 3]

        Collections.sort(list, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1 - o2;//升序 后减前 o2-o1降序  自定义的类也一样 o1.getAge() - o2.getAge()
            }
        });
        System.out.println(list);//[0, 1, 2, 3]

    }
}

List(接口 有序可重复)

  1. 有序的集合(存储和取出元素顺序相同)
  2. 允许存储重复的元素
  3. 有索引,可以使用普通的for循环遍历

ArrayList(常用 底层是数组实现的,查询快、增删慢


普通数组的长度不可以改变
ArrayList是大小可变的数组的实现

//<这里是泛型>  只能是引用类型,不能是基本类型
//也就是装在集合当中的所有元素统一成什么类型
ArrayList<String> list = new ArrayList<>();
System.out.println(list);//注:对于ArrayList集合 直接打印得到的不是地址 而是内容。 如果内容为空就是 []
//创建了一个ArrayList集合,集合名字为list,里面装的全是String字符串类型的数据
//备注 从JDK 1.7+ 开始 右边的<>里面可以不写,但是<>尖括号得写
常用方法

add 添加
public boolean add(E, e); 向集合中添加元素 参数类型和泛型一致
将指定元素添加到其尾部

list.add("AAA");
System.out.println(list);// [AAA]
list.add("BBB");
list.add("CCC");
System.out.println(list);//[AAA, BBB, CCC]
list.add(100);//出错 这里和上面代码连接起来的 泛型已经指定了是字符串类型

remove 删除
public E remove(int index); 从集合中删除元素,参数是索引编号,返回值就是被删除的元素

System.out.println("被删除的是"+list.remove(2));//被删除的是CCC

get 获取
public E get(int index); 从集合中获取元素,参数是索引编号,返回值就是对应位置的元素

System.out.println(list。get(0));//AAA

size 大小
public int size(); 获取集合的长度,返回值是集合中包含的元素个数

System.out.println("现在集合大小为"+list.size());//现在集合大小为2

遍历

for (int i=0; i<list.size(); i++){
	Sysouteem.out.println(list.get(i));
}

LinkedList(常用 底层是链表实现的,查询慢、增删快)

addFirst()
  • public void addFirst(E e) :将指定元素插入此列表的开头。
  • public void addlast(E e) :将指定元素添加到此列表的结尾。
  • public void push(E e):将元素推入此列表所表示的堆栈。
public static void show01(){
	LinkedList<String> list = new LinkedList<>();
	//add添加
	list.add("a");
	list.add("b");
	System.out.println(list);//[a, b]
	//addFitst插入开头
	list.addFirst("ww");//list.push("ww");效果一样
	System.out.println(list);//[ww, a, b]
	//addLast插入结尾 与add差不多
	list.addLast("c");
	System.out.println(list);//[ww, a, b, c]
}
removeFirst()
  • public E removeFirst() :移除并返回此列表的第一个元素 。
  • public E removeLast():移除并返回此列表的最后一个元素。
  • public E pop():从此列表所表示的堆栈处弹出一个元素。此方法相当于removeFirst
public static void show01(){//接着上面的[ww, a, b, c]
	。。。
	System.out.println( list.removeFirst() );//ww
	//这个时候第一个ww就被删除了
	System.out.println( list.removeLast() );//c
	//这个时候最后一个c被删除
	System.out.println(list);//[a, b]
}
getFirst()
public static void show01(){//接着上面的[ww, a, b, c]
	。。。
	//假设集合中没有元素 会抛出异常 所以最好添加isEmpty 是否为空 方法
	if( !list.isEmpty() ){//是否为空取反  是否不为空
		System.out.println( list.getFirst() );// ww
		System.out.println( list.getLast() );//  c
	}
}

Vector(了解 1.0)

底层也是数组 和ArrayList一样可以增长
但是他从1.2之后被取代了 因为他是单线程

Set(接口 存取无序不可重复)

  1. 不允许存储重复元素
  2. 没有索引(不能使用普通的for循环遍历)

HashSet(常用)

底层是哈希表+ (红黑树)实现的,无索引、不可以存储重复元素、存取无序

什么是哈希值?

哈希值:是一个十进制的整数,由系统随机给出
(就是对象的地址值,是一个逻辑地址, 是模拟出来得到地址,不是数据实际存储的物理地址)

在Object类中有一个方法int hashCode();,可以获取到对象的哈希值

public class Demo{
	public static void main(String[] args){
		//假如写了一个Person类
		Person p1 = new Person();
		int h1 = p1.hashCode();
		System.out.println(h1);//13672      |   1
//重写Person类中的hashCode方法 改为返回值1 就都是一了
		Person p2 = new Person();
		int h2 = p2.hashCode();
		System.out.println(h2);//78937458   |   1
		/*
			toString方法的源码:
				return getClass(). getName() + "@" + Integer. toHexString(hashCode());
		*/
		System.out.println(p1);//  ...@(p1.hashCode())的十六进制
		System.out.println(p2);//  ...@(p2.hashCode())的十六进制
		//即使重写之后他们都是1 但
		System.out.println(p1 == p2);//false
		//String类的哈希值 他也重写了hashCode方法
		String s1 = new String("abc");
		String s2 = new String("abc");
		System.out.println(s1.hashCode());//96354
		System.out.println(s2.hashCode());//96354

		//特殊 巧合
		System.out.println("重地".hashCode());//117939
		System.out.println("通话".hashCode());//117939
	}
}
什么是哈希表?

在JDK1.8之前,哈希表底层采用数组+链表实现,即使用链表处理冲突,同一hash值的链表都存储在一个链表里。
但是当位于一个桶中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。
而JDK1.8中,哈希表存储采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。

Set集合不允许重复的原理

注:必须重写hashCode和equals方法

public static main(String[] args){
	HashSet<String> set = new HashSet<>();
	String s1 = new String("abc");
	String s2 = new String("abc");
	set.add(s1);
	set.add(s2);
	set.add("重地");
	set.add("通话");
	set.add("abc");
	System.out.println(set);//[重地, 通话, abc]
}

Set集合在调用add方法的时候 会调用hashCode方法和equals方法 来判断是否重复
add(s1);先调用hashCode方法计算字符串"abc"的哈希值(假设96354)发现集合中没有这个哈希值的元素 就将s1存储到集合中
接着add(s2);同样得到了哈希值是96354 接着在调用s2的equals与哈希值相同的s1比较 (s2.equals(s1) 返回true) 两个元素的哈希值相同 equals方法返回true 就不存储
接着add(“重地”);如add(s1);
然后add(“通话”); 通话与重地的哈希值一样 然后 “通话”.equals(“重地”) 返回false 还是存储进去 挂到重地下面

在这里插入图片描述
自定义的类型存储(没有重写hashCode和equals方法)

public static void main(String[] args) {
        HashSet<Person> set = new HashSet<>();
        Person p1 = new Person("A",18);
        Person p2 = new Person("A",18);
        Person p3 = new Person("A",19);
        System.out.println(p1.hashCode());//284720968
        System.out.println(p2.hashCode());//189568618

		System.out.println(p1 == p2);//false
		System.out.println(p1.equals(p2));//false

        set.add(p1);
        set.add(p2);
        set.add(p3);
        System.out.println(set);//[Person{name='A', age=18}, Person{name='A', age=19}, Person{name='A', age=18}]
    }

这样就不能满足 不能存储相同的人(名字年龄一样)所以重写hashCode和equals方法
Alt+ins

System.out.println(p1.hashCode());//2994
System.out.println(p2.hashCode());//2994

System.out.println(p1 == p2);//false
System.out.println(p1.equals(p2));//true

System.out.println(set);//[Person{name='A', age=18}, Person{name='A', age=19}]
LinkedHashSet(有序 存储有序不可重复)

底层是哈希表(数组+链表/红黑树)+链表(多了一条链表(记录元素的存储顺序),保证元素有序)实现的,无索引、不可以存储重复元素

TreeSet(了解)

底层是二叉树实现。一般用于排序

Map

Map<K,V>(接口)
Key 键 Value 值

  1. Map集合是一个双列集合,一个元素包含两个值(Key Value)
  2. Key 和 Value的数据类型可以不同也可以相同
  3. Key不能重复 Value可以重复
  4. 键和值 —— 映射关系 (一个键对应一个值)再来一个直接被替换

添加

public V put(K key, V value) 把指定的键与指定的值添加到Map集合中。

private static void show01() {
/*
public V put(K key, V value)` 把指定的键与指定的值添加到Map集合中。
存储键值对的时候,key不重复,返回值V是null
存储键值对的时候,key重复,会使用新的value替换map中重复的value,返回被替换的value值
*/
        //创建Map 多态
        Map<String, String> map = new HashMap<>();

        String v1 = map.put("第一个","AAA");
        System.out.println(v1);//没有重复的key  所以输出 null

        String v2 = map.put("第一个","BBB");
        System.out.println(v2);//有重复的key  告诉你被覆盖的是AAA 所以输出 AAA

        System.out.println(map); //{第一个=BBB}

        map.put("第二个","BBB");//value重复没事
        System.out.println(map);//{第二个=BBB, 第一个=BBB}
    }

删除

public V remove(object key) 把指定的键所对应的键值对元素在Map集合中删除,返回被删除元素的值。

 /*
    public V remove(object key) 把指定的键所对应的键值对元素在Map集合中删除,返回被删除元素的值。
        返回值:V
            key存在, v返回被删除的值
            key不存在,v返回null
     */
    private static void show02() {
        //创建Map 多态
        Map<String, Integer> map = new HashMap<>();

        map.put("长度1",123);
        map.put("长度2",456);
        map.put("长度3",444);
        System.out.println(map);//{长度3=444, 长度1=123, 长度2=456}

        Integer v1 = map.remove("长度1");//返回的就是被删除的值 是Integer类型
        System.out.println(v1);//123

        Integer v2 = map.remove("长度9999");
        System.out.println(v2);//null

        System.out.println(map);//{长度3=444, 长度2=456}
    }

根据K获取对应V

public V get(object key) 根据指定的键,在Map集合中获取对应的值。

 private static void show03(){
        //创建Map 多态
        Map<String, Integer> map = new HashMap<>();

        map.put("长度1",123);
        map.put("长度2",456);
        map.put("长度3",444);

        Integer v1 = map.get("长度1");
        System.out.println(v1);//123

        Integer v2 = map.get("长度9999");
        System.out.println(v2);//null
    }

根据K/V判断是否存在

boolean containsKey(object key) 判断集合中是否包含指定的键。

/*
        boolean containsKey(object key) 判断集合中是否包含指定的键。
        boolean containsValue(object value) 判断集合中是否包含指定的键。
        包含返回true,不包含返回false
    */
    private static void show04(){
        //创建Map 多态
        Map<String, Integer> map = new HashMap<>();

        map.put("长度1",123);
        map.put("长度2",456);
        map.put("长度3",444);

        boolean b1 = map.containsKey("长度1");
        boolean b2 = map.containsKey("长度999");
        System.out.println("b1:" + b1 + " b2:" + b2);//b1:true b2:false

        boolean b11 = map.containsValue(123);
        boolean b22 = map.containsValue(213213);
        System.out.println("b11:" + b11 + " b22:" + b22);//b11:true b22:false

    }

Map遍历

public Set<K> keySet() 获取Map集合中所有的键,存储到Set集合中。
在这里插入图片描述

public static void main(String[] args) {
        //创建Map 多态
        Map<String, Integer> map = new HashMap<>();

        map.put("长度1",123);
        map.put("长度2",456);
        map.put("长度3",444);
        //1.使用Map集合中的方法keySet(),把Map集合所有的key取出来,存储到一个Set集合中
        Set<String> set = map.keySet();
        //2.遍历set集合,获取Mop集合中的每一个key,
        for (String key: set) {
            //3.通过Map集合中的方法get(key),通过key找到value
            System.out.println(key + " " + map.get(key));
        }

        System.out.println("==============================");
        //2.遍历set集合,获取Mop集合中的每一个key,
        Iterator<String> it = set.iterator();
        while (it.hasNext()){
            String key = it.next();
            //3.通过Map集合中的方法get(key),通过key找到value
            Integer value = map.get(key);
            System.out.println(key +" "+ value);
        }
    }

public Set<Map. Entry<K,V>> entrySet() 获取到Map集合中所有的键值对对象的集合(Set集合)。

/*
Map集合遍历的第二种方式:使用Entry对象遍历
Map集合中的方法: 
Set<Map. Entry<K,V>> entrySet() 返回此映射中包含的映射关系的Set视图。
实现步骤:
    1.使用Map集合中的方法entrySet(),把Map集合中多个Entry对象取出来,存储到一个Set集合中
    2.遍历Set集合,获取每一个Entry对象
    3.使用Entry对象中的方法getKey( )和getValue( )获取键与值
 */
public class Demo06SetEntryset {
    public static void main(String[] args) {
        //创建Map 多态
        Map<String, Integer> map = new HashMap<>();

        map.put("长度1",123);
        map.put("长度2",456);
        map.put("长度3",444);
        //1.使用Map集合中的方法entrySet(),把Map集合中多个Entry对象取出来,存储到一个Set集合中
        Set<Map.Entry<String, Integer>> set = map.entrySet();
        
        //2.遍历Set集合,获取每一个Entry对象
        Iterator<Map.Entry<String, Integer>> it = set.iterator();
        while (it.hasNext()){
            Map.Entry<String, Integer> entry = it.next();
            //3.使用Entry对象中的方法getKey( )和getValue( )获取键与值
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key + " " + value);
        }

        System.out.println("=============================");

        for(Map.Entry<String, Integer> entry : set){
            String Key = entry.getKey();
            Integer Value = entry.getValue();
            System.out.println(Key + " " + Value);
        }
    }
}

HashMap(重点)

  1. HashMap集合底层是哈希表,查询特别快

JDK1.8之前:数组+单向链表
JDK1.8之后:数组+单向链表/红黑树(链表的长度超过8) :提高查询的速度

  1. hashMap集合是一个无序的集合, 存储元素和取出元素的顺序有可能不一致
    详解

应用(使用HashMap存储自定义类型的键值)

/*
HashMap存储自定义类型键值
    Map集合保证key是唯一的:
    作为key的元素, 必须重写hashCode方法和equals方法,以保证key唯一
*/
 
public class Demo06自定义类型 {
    public static void main(String[] args) {
//        HashMap<String,Person> map = new HashMap<>();
//        map.put("第一个", new Person("A", 12));//13
//        map.put("第二个", new Person("B", 13));//14
//        map.put("第三个", new Person("A", 12));//15
//        map.put("第一个", new Person("C", 19));//16
//
//        System.out.println(map);//{第二个=Person{name='B', age=13}, 第三个=Person{name='A', age=12}, 第一个=Person{name='C', age=19}}
        //输出因为16和13的key相同 16覆盖了13  但是相同的value就没事(这个时候还没有重写Person的equals和hashCode方法)
        //即使重写了equals和hashCode方法相同的还是可以存进去 因为主要是看key

        HashMap<Person, String> map = new HashMap<>();
        map.put(new Person("A", 12), "value1");
        map.put(new Person("B", 19), "value2");
        map.put(new Person("A", 12), "value3");
        map.put(new Person("A", 100), "value4");

        System.out.println(map);//假设没有重写equals和hashCode方法 就4个都存入输出了 不满足key相同这个问题
        //重写之后 value3就覆盖了value1

    }
}

LinkedHashMap(extends HashMap)

  1. LinkedHashMap集合底层是哈希表 + 链表(保证迭代的顺序)
  2. LinkedHashMap集合是一个有序的集合,存储元素和取出元素的顺序是一致的
/*
    java.util.LinkedHashMap<K, V> extends HashMap<K, V>
        Map接口的哈希表和链接列表实现,具有可预知的迭代顺序。
        底层原理:
        哈希表+链表(记录元素的顺序)
 */
public class Demo06Linked {
    public static void main(String[] args) {
        LinkedHashMap<String, String> linked = new LinkedHashMap<>();
        linked.put("1", "a");
        linked.put("2", "b");
        linked.put("3", "c");
        linked.put("1", "d");
        System.out.println(linked);//{1=d, 2=b, 3=c} 有序的
    }
}

Hashtable

  • java.util.Hashtable<K, V>集合 implements Map<K, V>接口
  • Hashtable:底层也是一个哈希表,是一个线程安全的集合;是单线程集合,速度慢
  • HashMap:底层是一个哈希表,是一个线程不安全的集合,是多线程的集合,速度快
  • HashMap集合(以及之前学的所有的集合):可以存储null值, null键
  • Hashtable集合,不能存储null值, null键
  • Hashtable和vector集合一样,在jdk1.2版本之后被更先进的集合(HashMap,Arraylist )取代了
  • Hashtable的子类Propert ies依然再用
  • Properties集合是一个唯一和IO流相结合的集合

集合的补充

JDK9的新特性:
List接口, Set接口,Map接口:里边增加了一个静态的方法of,可以给集合一次性添加多个元素

static <E> List<E> of (E... elements)

使用前提:
当集合中存储的元素的个数已经确定了,不在改变时使用
注意:
1.of方法只适用于List接口, Set接口,Map接口,不适用于接接口的实现类
2. of方法的返回值是一个不能改变的集合,集合不能再使用add, put方法添加元素,会抛出异常
3. Set接口和Map接口在调用of方法的时候,不能有重复的元素,否则会抛出异常

快速创建不可变的集合

List<String> list = List.of("a","b","c");
Set<String> set = Set.of("A","B","c");
Map<Integer,Integer> map = Map.of(1,1 , 2,2 );
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值