Java -- 关于集合新手应该掌握的

现在的程序中,怎么存放多个数据? ------- 在学习集合之前就知道 数组
数组缺点:只能存放相同类型的数据。长度不可变。遍历方式单一。

由于数组存在缺点,所以产生了多种集合。

集合类存放于java.util包中;

集合类存放的都是对象的引用,而非对象本身,出于表达上的便利,我们称集合中的对象就是指集合中对象的引用(reference);

集合类型主要有3种:set(集)、list(列表)和map(映射);
集合接口分为:Collection和Map,list、set实现了Collection接口

一、Collection

(一)概述

英文名称Collection,是用来存放对象的数据结构,其长度可变,而且集合中可以存放不同类型的对象,并
提供了一组操作成批对象的方法。数组的缺点:长度是固定不可变的,访问方式单一,插入。删除等操作繁琐。

(二)Collection继承结构

在这里插入图片描述

Collection接口
list接口:数据有序,可以重复
ArrayList子类
LinkedList子类
Set接口:数据无序,不可以存重复值
HashSet子类
Map接口:键值对存数据
HashMap

Conllections工具类

(三)常用方法

package cn.tedu.collection;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;

//这个类用来测试Collection接口
public class Test_Collection {
	public static void main(String[] args) {
		//1、创建对象
		Collection<String> col = new ArrayList<>();
		//2、常用方法
		col.add("jack");//添加元素
		col.add("韩美美");
		col.add("rose1");
		col.add("rose2");
//		col.add(100);
//		col.clear();//清空集合
		
		System.out.println(col.contains("jack"));//判断集合中是否包含指定元素
		System.out.println(col.equals("韩美美")+"----");//判断集合是否和指定元素相等
		System.out.println(col.hashCode());//返回集合对象在内存中的哈希码值
		System.out.println(col.isEmpty());//判断是否为空,空返回true,不为空返回false
		System.out.println(col.remove("rose1"));//移出某个元素,返回是否删除成功
		System.out.println(col.size());//获取集合的长度
		System.out.println(Arrays.toString(col.toArray()));//把集合转成Object[]数组
		
		//集合间的操作
		Collection<String> col2 = new ArrayList<>();
		col2.add("1");
		col2.add("2");
		System.out.println(col.addAll(col2));//向col集合中添加col2集合的元素
		System.out.println(col.containsAll(col2));//判断col中是否包含col2的元素
//		System.out.println(col.removeAll(col2));//删除col集合中的col2的元素
//		System.out.println(col.retainAll(col2));//删除col集合的元素
		System.out.println(col);
		
		//迭代器:迭代/遍历集合中的元素
		Iterator it = col.iterator();
		while (it.hasNext()) {//hasNext()判断集合中有下一个元素吗
			System.out.println(it.next());//next()获取遍历到的元素
		}
	}
}


二、list接口

(一)概述

1.有序的Collection(也成为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制、
用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素;

2.与set不同,列表通常允许重复的元素;

(二)特点

1.数据有序
2.允许存放重复数组
3.元素都有缩影

(三)常用方法
package cn.tedu.collection;

import java.util.HashSet;
import java.util.Iterator;

//这个类用来测试Set集合去重
/*
 * 总结:
 * 	如果想要使用set集合,给你的自定义对象去重的话,需要同时重写hashCode()和equals()
 * 	重写hashCode():原来的实现方式是:只要new就会给计算一个新的哈希码值
 * 			现在需要按照对象的属性值计算哈希码值,就算new两次,属性值一样时也必须产生相同哈希码值
 * 	重写equals():原来比的是两个对象间的地址值,现在要去比较两个对象间的属性值,如果属性值都一样,必须
 */
public class Test_Set {
	public static void main(String[] args) {
		HashSet<Student> set = new HashSet<>();
		//创建元素
		Student s1 = new Student("西门庆",20);
		Student s2 = new Student("武大郎",19);
		Student s3 = new Student("潘金莲",21);
		Student s4 = new Student("小龙女",23);
		//添加时,新元素会和老元素比
		set.add(s1);
		set.add(s2);
		set.add(s3);
		set.add(s4);

		//往set中添加重复元素
		Student s5 = new Student("武大郎",19);
		Student s6 = new Student("潘金莲",21);
		//默认:添加时查找对象的hash值,没有查到就存起来
		//所以必须让hash值一致才可以
		set.add(s5);
       	set.add(s6);
       	//问题1:属性相同时还是认为是两个对象...
       	
       	System.out.println(set);
//       	System.out.println(s2.hashCode());
//       	System.out.println(s5.hashCode());
       	
       	//遍历
       	Iterator it = set.iterator();
       	while(it.hasNext()) {
       		System.out.println(it.next());
       	}
    }
}
	 
//创建Student类/	 
class Student {
	private String name;
    private int age;
    
    public Student(String name, int age) {
    	this.name = name;
    	this.age = age;
    }
    public Student() {
    }
    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
    public boolean equals(Object obj) {
    	if (this == obj)
    		return true;
    	if (obj == null)
    		return false;
    	if (getClass() != obj.getClass())
    		return false;
    	Student other = (Student) obj;
    	if (age != other.age)
    		return false;
    	if (name == null) {
    		if (other.name != null)
    			return false;
    	} else if (!name.equals(other.name))
    		return false;
    	return true;
    }
    
	//HashSet默认:添加时查找对象的hash值,没有查到就存起来
	//所以必须让hash值一致才可以
    //必须用算法,不然的话,hash值相同时会挂一串
	public int hashCode() {
		//return 0;//效率低
		//让基本类型*31,引用类型就用自己的hash值
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
    }
}


三、ArrayList子类

(一)概述

1.存在于java util包中
2.内部用数组存放数据,封装了数组的操作,每个对象都有下标
3.内部数组默认初识容量是10。如果不构会以1.5倍容量增长、
4.查询快,增删数据效率会降低

(二)创建对象
new ArrayList();//初始容量是10

(三)测试案例
package cn.tedu.collection;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

//这个类用来测试ArrayList
public class Test_ArrayList {
	public static void main(String[] args) {
		//1、创建对象
		/*
		 * ArrayList特点:
		 * 	1、底层是个数组,所以适合查询,不适合增删
		 * 	2、底层会为数组自动扩容,1.5倍方式扩容:
		 */
		List<String> list = new ArrayList<>();
		
		//2、常见方法
		list.add("aaa");//存入数据
		list.add("123");
		list.add("ccc");
		list.add("ddd");
		System.out.println(list);//list中内容
		System.out.println(list.size());//集合长度
		System.out.println(list.get(1));//根据下标获取元素
		        
		System.out.println();
		System.out.println(list.remove(2));//移除下标对应的元素
		System.out.println(list);
		
		//下标遍历
        for (int i = 0; i < list.size(); i++) {
               System.out.print(list.get(i));
        }
        //Iterator迭代遍历,封装了下标
        Iterator<String> it = list.iterator();
        while (it.hasNext()) {//如果有数据
        	String s = it.next();//一个一个向后遍历
        	System.out.println(s);
    	}      
	}
}


四、LinkedList子类

(一)概述

双向链表,两端效率高。底层就是数组和链表实现的。

在这里插入图片描述

(二)特点

1.底层维护了一个链表结构;
2.适用于增删多而查询少的场景;
3.对与链表中的节点操作效率并不高,但是对与首尾两个节点操作效率高。

(三)创建对象
LinkedList<E> list = new LinkedList<>();
(四)常见方法
package cn.tedu.collection;

import java.util.Iterator;
import java.util.LinkedList;

public class Test_LinkedList {
	public static void main(String[] args) {
		//1、创建对象
		//特点:和list一样,元素有序,可以重复
		LinkedList<Integer> list = new LinkedList<>();
		//2、常用方法
		list.add(100);
		list.add(200);
		list.add(300);
		list.add(400);
		list.add(500);
		System.out.println(list);
		
		list.addFirst(0);//添加首元素
		list.addLast(99);//添加尾元素
		System.out.println(list);
		
		System.out.println(list.getFirst());//获取首元素
		System.out.println(list.getLast());//获取尾元素
		System.out.println(list+"=====");
		
		System.out.println(list.removeFirst());//移出首元素
		System.out.println(list.removeLast());//移出尾元素
		System.out.println(list);
		
		//3、查询效率for  iterator
		
		for (int i = 0; i < list.size(); i++) {
			System.out.println(list.get(i));
		}
		System.out.println("============");
		//迭代查询
		Iterator<Integer> it = list.iterator();
		while (it.hasNext()) {
//			System.out.println(it.next());
			Integer in=it.next();
			System.out.println(in);
		}
	}
}


五、Set接口

(一)概述

1.一个不包含重复元素的Collection;
2.数据无序(因为set集合没有下标);
3,由于集合中的元素不可以重复,常用与给数据去重;

(二)特点

1.HashSet:底层是哈希表,包装了HashMap,相当于向HashSet中存入数据时,会把数据作为K,存入内部
的HashMap中,当然K仍然不需重复;

2.TreeSet:底层就是TreeMap,也是红黑树形式,便于查找数据

3.HashMap:事项总,当hash值相同的对象,会在同一个hash值得位置存储不用属性的数据。

(三)常用方法
package cn.tedu.collection;

import java.util.HashSet;
import java.util.Iterator;

//这个类用来测试Set集合去重
/*
 * 总结:
 * 	如果想要使用set集合,给你的自定义对象去重的话,需要同时重写hashCode()和equals()
 * 	重写hashCode():原来的实现方式是:只要new就会给计算一个新的哈希码值
 * 			现在需要按照对象的属性值计算哈希码值,就算new两次,属性值一样时也必须产生相同哈希码值
 * 	重写equals():原来比的是两个对象间的地址值,现在要去比较两个对象间的属性值,如果属性值都一样,必须
 */
public class Test_Set {
	public static void main(String[] args) {
		HashSet<Student> set = new HashSet<>();
		//创建元素
		Student s1 = new Student("西门庆",20);
		Student s2 = new Student("武大郎",19);
		Student s3 = new Student("潘金莲",21);
		Student s4 = new Student("小龙女",23);
		//添加时,新元素会和老元素比
		set.add(s1);
		set.add(s2);
		set.add(s3);
		set.add(s4);

		//往set中添加重复元素
		Student s5 = new Student("武大郎",19);
		Student s6 = new Student("潘金莲",21);
		//默认:添加时查找对象的hash值,没有查到就存起来
		//所以必须让hash值一致才可以
		set.add(s5);
       	set.add(s6);
       	//问题1:属性相同时还是认为是两个对象...
       	
       	System.out.println(set);
//       	System.out.println(s2.hashCode());
//       	System.out.println(s5.hashCode());
       	
       	//遍历
       	Iterator it = set.iterator();
       	while(it.hasNext()) {
       		System.out.println(it.next());
       	}
    }
}
	 
//创建Student类/	 
class Student {
	private String name;
    private int age;
    
    public Student(String name, int age) {
    	this.name = name;
    	this.age = age;
    }
    public Student() {
    }
    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
    public boolean equals(Object obj) {
    	if (this == obj)
    		return true;
    	if (obj == null)
    		return false;
    	if (getClass() != obj.getClass())
    		return false;
    	Student other = (Student) obj;
    	if (age != other.age)
    		return false;
    	if (name == null) {
    		if (other.name != null)
    			return false;
    	} else if (!name.equals(other.name))
    		return false;
    	return true;
    }
    
	//HashSet默认:添加时查找对象的hash值,没有查到就存起来
	//所以必须让hash值一致才可以
    //必须用算法,不然的话,hash值相同时会挂一串
	public int hashCode() {
		//return 0;//效率低
		//让基本类型*31,引用类型就用自己的hash值
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
    }
}


(六)HashSet子类

(一)概述

此类实现Set接口,有哈希表(实际上是一个HashMap实例)支持

他不保证set的迭代顺序;特别是他不保证顺序恒久不变。

此类允许使用null元素。

(二)创建对象
Set<E> set = new HashSet<>();
(三) 常用方法
package cn.tedu.collection;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class Test_HashSet {
	public static void main(String[] args) {
		//1、创建对象
		Set<Integer> set = new HashSet<>();
		
		//2、常用方法
		set.add(10);
		set.add(2);
		set.add(3);
		set.add(4);
		set.add(5);

		set.add(4);
		set.add(5);
		
		//set集合的特点:元素无序,元素不能重复
		System.out.println(set);
		
		//TODO 测试常用方法,与collection一样
		
		//迭代遍历
		Iterator it = set.iterator();
	    while(it.hasNext()) {
	    	System.out.println(it.next());
	    }
	}
}


(七) Map接口

(一)概述

1.java util接口key<K,V)
2.类型参数:K-此映射所维护的键的类型,V-映射值得类型。
3.也叫哈希表、散列表。常用于存 键值对 结构的数据。其中的键不能重复,值可以重复

(二)特点

可以根据键 提取对应的值;
键不允许重复,如果重复值会被覆盖;
存放的都是无序数据
初始容量是16,默认的加载因子是0.75

(继承结构)

在这里插入图片描述

(四)常用方法
package cn.tedu.Map;

import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

//这个类用来测试Map接口
public class Test_Map {
	public static void main(String[] args) {
		//1、创建map对象
		Map<Integer, String> map = new HashMap<>();
		
		//2、常用方法
		//向map集合中添加数据时,需要同时指定key和value的值
		map.put(9529, "秋香");
		map.put(9527, "唐伯虎");
		map.put(9528, "如花");
		map.put(9528, "石榴姐");
		/*
		 * 特点:
		 * 	1、数据无序 
		 * 	2、当key相同时,value值被覆盖 
		 */
		System.out.println(map);
		
//		map.clear();
		System.out.println(map.containsKey(9527));//是否包含指定的key
		System.out.println(map.containsValue("如花"));//是否包含指定的value
		System.out.println(map.equals("石榴姐"));//判断两者是否相等
		System.out.println(map.get(9528));//根据指定的key,找到对应的value
		System.out.println(map.hashCode());//计算map在内存中的哈希码值
		System.out.println(map.isEmpty());//判断集合是否为空
		System.out.println(map.size());//返回集合的长度
		System.out.println(map.remove(9527));//根据key删除元素,并把value返回
		
		Collection<String> col = map.values();//把map中的所有值获取到并存入collection中
		System.out.println(col);//打印
		
		//迭代map集合
//		Set<E> keySet()
//		Set<Map.Entry<K, V>> entrySet()
		//1、把所有的key放入set中,遍历set
		Set<Integer> set = map.keySet();//把所有的key放入set中
		
		//foreach可以用在数组遍历时,或者List遍历时,或者Set遍历时
		for (Integer integer : set) {
			String value = map.get(integer);
			System.out.println("foreach遍历:key-"+integer+",value-"+value);
		}

		Iterator<Integer> it = set.iterator();
		while (it.hasNext()) {
			Integer key = (Integer) it.next();//获取set中的元素,也就是每个key
			String value = map.get(key);//拿着每个key去map里面找对应的value
			System.out.println(key +"===="+ value);
		}
		
		//2、把所有的key和value封装成Entry对象,并放入set中,遍历set
		Set<Entry<Integer, String>> set2 = map.entrySet();
		Iterator<Entry<Integer, String>> it2 = set2.iterator();
		while (it2.hasNext()) {
			Map.Entry<Integer, String> entry = (Map.Entry<Integer, String>) it2
					.next();//遍历set得到每个entry对象
			Integer key = entry.getKey();//获取每个key
			String value = entry.getValue();//获取每个value
			System.out.println(key+"----"+value);
		}
	}
}


(八) HashMap

hashMap的键要是用时重写hashCode()和equals()

hashCode()用来判断确定hash值是否相同
equals()用来判断属性的值是否相同
equals()判断数据如果相等,hashCode()必须相同
equals()判断数据如果不等,hashCode()尽量不同
(一)概述

基于哈希表的Map接口实现。次实现提供所有可选的映射操作,并允许使用Null值和null键

hashMap底层是一个Entry数组,当存放数据时会根据hash算法计算数据的存放位置;

算法:hash(key)%n,n就是数组的长度‘

当计算的位置没有数据时,就直接存放,当计算有数据时也就是发生hash冲突的时候、hash碰撞时,采用链表的方式来解决的,再对应的数据位置存放链表的头节点;

对链表而言,新加入的节点会从头节点加入;

在这里插入图片描述

(原理)

当需要向map中存储元素时,底层会根据hash算法计算对象的存储位置;

如果这个位置上没有存过元素,就直接存放,就相当于直接作为数组的元素存在;

如果这个位置上存过数据,就会形成链表的结构–hash碰撞/冲突;

我们尽量要让每个对象拥有自己的哈希值,尽量放在数组结构上。避免链表的形成,因为链 表查询效率低。

package cn.tedu.Map;

import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class Test_HashMap {
	public static void main(String[] args) {
		//1、创建对象
		Map<String, String> map = new HashMap<>();
		
		//2、存数据
		map.put("1", "jack");
		map.put("2", "rose");
		map.put("3", "tom");
		map.put("4", "jerry");
		
		//3、迭代map集合 -- keySet()  entrySet()
		Set<String> set = map.keySet();//把key放在set里
		for (String key : set) {//遍历set得到每个key
			String value = map.get(key);
			System.out.println(key + "-----" + value);
		}
		
		//把map里的每条记录封装成Entry对象存入set
		Set<Entry<String,String>> set2 = map.entrySet();
		for (Entry<String, String> entry : set2) {//遍历set得到每个Entry对象
			System.out.println(entry.getKey()+ "====="+ entry.getValue());
		}
	}
}


在这里插入图片描述

(四)统计字符串中出现的次数
package cn.tedu.Map;

import java.util.HashMap;
import java.util.Scanner;

public class Test2_Map {
	public static void main(String[] args) {
		//1、接收用户输入的字符串
		String input = new Scanner(System.in).nextLine();
		
		//定义map存数据 -- 类似于a=1,b=2,c=5
		HashMap<Character, Integer> map = new HashMap<>();
		
		//2、遍历字符串,获取每个字符
		/*
		 * 字符串长度用:length()
		 * 数组长度用:size()
		 */
		for (int i = 0; i < input.length(); i++) {
			char key = input.charAt(i);//根据下标获取对应的字符
			
			//3、统计字符出现过几次 -- map里的value是多少
			Integer value = map.get(key);
			if (value == null) {//如果之前没有存过字符,value存的就是默认值null
				map.put(key, 1);//把value中的默认值null改成1,说明第一次统计这个字符的次数
			}else {//如果value不是默认值,也就是之前统计过了
				map.put(key, value+1);	//把value的值改成原来的数字+1,就ok了
			}
		}
		System.out.println(map);
	}
}

(九)Collections工具类

(一)常用方法

1.Collections.sort(List<> list):根据元素的自然顺序 对指定列表按升序进行排序;

2.Collections.max():根据元素的自然顺序,返回给定 collection 的最大元素;

3.Collections.min():根据元素的自然顺序 返回给定 collection 的最小元素;

4.Collections.swap(List,i,j):在指定列表的指定位置处交换元素;

5.Collections.addAll():

(二)测试案例
package seday12;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Test4_Collections {
       public static void main(String[] args) {
              List<String> list = new ArrayList();
              
              //添加多个元素
              Collections.addAll(list, 
                            "3","30","23","15","29","12","26");
              
              //元素排序
              Collections.sort(list);
          //默认是字符顺序:[12,15,23,26,29, 3, 30]
              System.out.println(list);
              
              //自己定义比较方式
              Collections.sort(list, new Comparator<String>() {
                     //自定义比较器,sort()自动调用
                     @Override
                     public int compare(String o1, String o2) {
                            //把字符串转成int比大小
                            int a = Integer.parseInt(o1);
                            int b = Integer.parseInt(o2);
//o1大是正数,o1小是负数,相等是0
                            return a-b;
                     }
              });
              System.out.println(list);
       }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZangChen.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值