Java集合概述 学习笔记

Java 集合概述

Java集合类存放在java.util包中,是一个用来存放对象的容器

  • 集合只能存放对象,比如存一个int型数据1放入集合中,其实它时自动转换成Integer类后存入的,Java中每一种基本类型都有对应的引用类型
  • 集合存放的是多对象的引用,对象本身还是放在堆内存中
  • 集合可以存放不同类型,不限数量的数据类型

Java集合可分成Set、List和Map三大体系

  • Set: 无序、不可重复的集合
  • List:有序、可重复的集合
  • Map:具有映射关系的集合

注:JDK5后,增加了泛型,Java集合可以记住容器中对象的数据类型

1.HashSet

Hashset是Set接口的典型实现,大多数时候使用Set集合时都使用这个实现类。大多时候说的Set集合指的就是HashSet
HashSet按照Hash算法来存储集合中的元素,具有很好的存取和查找性能
HashSet具有以下特点:

  • 不能保证元素的排列顺序(存在set集合哪个位置由这个位置的hashcode决定)
  • 不可重复(指的是hashCode不相同)
  • HashSet不是线程安全的
  • 集合元素可以存储null

当向HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据hashCode值决定该对象在HashSet的存储位置
如果两个元素的equals()方法返回true,但它们的hashCode()返回值不相等,hashSet将会把它们存储在不同的位置,依然可以添加成功

public class Test{
	public static void main(String[] args){
		Set set = new HashSet();
		Set<String> set1 = new HashSet<String>();//指定为String类型的泛型
		set.add(1);//添加元素
		set.add("a");
		set.remove(1);//移除元素
		set.contains(1);//判断是否包含该元素
		set.clear()//清空元素
		set.add("a");
		set.add("b");
		set.add("c");
		//使用迭代器遍历集合
		Iterator it = set.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
		//for each迭代集合
		for(Object obj:set){//把set集合中的每一个值取出来,赋值给obj,直到循环set的所有值
			System.out.println(obj);
		}
	}
}
/*HashSet集合判断两个元素相等的标准:两个对象通过equals()方法比较相等,
并且两个对象的hashCode()方法返回值也相等*/

2.TreeSet

TreeSet 是SortedSet接口的实现类,TreeSet可以确保集合元素处于排序状态,TreeSet支持两种排序方式: 自然排序和定制排序。默认情况下,TreeSet采用自然排序

自然排序

排序:TreeSet会调用集合元素的compareTo(Object obj)方法来比较元素之间的大小关系,然后将集合元素按升序排列

  • 若this>obj,return 1;
  • 若this<obj,return -1;
  • 若this==obj,return 0;认为这两个对象相等
  • 必须放入同样类的对象(默认会进行排序)否则可能会发生类型转换异常,我们可以使用泛型来进行限制
定制排序

若需要实现定制排序,则需要在创建TreeSet集合对象时,提供一个Comparator接口的实现类对象,由该Comparator对象负责集合元素的排列逻辑

public class Test{
	public static void main(String[] args){
		Person p1 = new Person("张山",22);
		Person p2 = new Person("李四",20);
		Person p3 = new Person("王五",27);
		Person p4 = new Person("六一",23);
		Set<Person> set = new TreeSet<Person>(new Person());
		set.add(p1);
		set.add(p2);
		set.add(p3);
		set.add(p4);
		for(Person p:sset){
		System.out.println(p.name+"  "+p.age);
	}
}
class Person implements Comparetor<Person>{
	private String name;
	private int age;
	public Person(){}
	public Person(String name,int age){
		this.name = name;
		this.age = age;
	}
	@Override
	public int compare(Person o1,Person 02){//正序排列
		if(o1.age>o2.age) return 1;
		else if(o1.age>o2.age) return -1;
		else return 0;
	}
}

3.List与ArrayList

List代表一个元素有序、且可重复的集合,集合中的每个元素都有其对应的顺序索引

public class Test{
	public static void main(String[] args){
		List<String> list = new ArrayList<String>();
		list.add("b");//第一个,索引下标为0
		list.add("d");
		list.add("c");
		list.add("b");//允许使用重复元素
		System.out.println(list.get(2));//通过索引来访问指定位置的集合元素
		list.add(1,"f");//在指定索引下标的位置插入数据
		
		List<String> s = new ArraayLlist<String>();
		s.add("123");
		s.add("345");
		list.addAll(2,s);//在指定索引下标的位置插入s集合
		System.out.println(list);
		System.out.println(list.indexof("d"));//获取指定元素在集合中第一次出现的索引下标
		System.out.println(list.lastIndexof("d"));//获取指定元素在集合中最后一次出现的索引下标
		list.remove(2);//根据指定索引位置移除元素
		list.set(1,"fff");//根据指定的索引下标修改元素
		
		//根据索引下的起始位置截取一段元素形成一个新的集合,截取的时间,
		//包含开始的索引不包含结束的索引
		List<String> sublist = list.subList(2,4);//取索引下标在>=2,<4的元素
		System.out.println(sublist);
	}
}

4.Map与HashMap

Map用于保存具有映射关系的数据,因此Map集合里保存着两组值,一组值用于保存Map里的Key,另外一组用于保存Map里的Value
Map中的key和value都可以是任何引用类型的数据,Map中的Key不允许重复,即同一个Map对象的任何两个Key通过equals方法比较中返回false
Key和Value之间存在单向一对一关系,即通过指定的Key总能找到唯一的,确定的Value

public class Test{
	public static void main(String[] args){
		Map<String,Integer> map = new HashMap<String,Integet>();
		map.put("b",1);//添加数据
		map.put("c",4);
		map.put("s",3);
		System.out.println(map.get("b"));//输出1,根据key值取value值
		map.remove("c");//根据key移除键值对
		System.out.println(map.containsKey("a"));//判断当前map集合是否包含指定的key
		System.out.println(map.containsValue(3));//判断当前map集合是否包含指定的value
		Set<String> keys = map.keySet();//获取map集合的key的集合
		Set<Integer> values = map.values();//获取map集合的所有value
		//遍历map集合,通过map.keySet()
		for(String key:keys){
			System.out.println("key:"+key+","+"value:"+map.get(key));
		}
		//通过map.entrySet()
		Set<Entry<String,Integer>> entrys = map.entrySet();
		for(Entry<String,Integer> en:entrys){
			System.out.println("key:"+en.getKey()+","+"value:"+en.getValue());
		}
	}
/*HashMap和Hashtable是map接口的两个典型实现类
Hashtable是线程安全的Map实现类,HashMap线程不安全
Hashtable不允许使用null作为key和value,而HashMap可以
Hashmap、Hashtable判断两个value相等的标准:
	两个value通过equalHashMap判断两个values方法返回true
Hashmap、Hashtable判断两个key相等的标准:
	两个key通过equals方法返回true,hashCode值也相等*/
}

5.TreeMap

TreeMap存储key-value对时,需要根据key对key-value对进行排序,TreeMap可以保证所有的key-value对处于有序状态
TreeMap对key的排序:

  • 自然排序
    TreeMap的所有的key必须实现comparable接口,而且所有的key应该是同一个类的对象
  • 制定排序
    创建TreeMap时,传入一个Comparator对象,该对象负责对TreeMap中的所有key进行排序,此时不需要Map的key实现Comparable接口
public class Test{
	public static void main(String[] args){
		Map<Integer,String> map = new TreeMap<Integer,String>();
		map.put(1,"a");
		map.put(4,"a");
		map.put(2,"a");
		map.put(3,"a");
		System.out.println(map);//TreeMap的自然排序是字典排序
	}
}

6.Collections[操作集合的工具类]

Collections是一个操作Set、List和Map等集合的工具类

public class Test{
	public static void main(String[] args){
		List<String> list = new ArrayList<String>();
		list.add("b");
		list.add("ddd");
		list.add("av");
		Collections.reverse(list);//反转list中元素的顺序
		System.out.println(list);
		Collections.shuffle(list);//对list集合元素进行随机排序
		Collections.sort(list);//list集合字典升序排列
		System.out.println(Collections.frequency(list,"x"));//返回指定集合中指定元素的出现次数
		Collections.swap(list,0,2);//将指定list集合中的i[0]处元素和j[2]处元素进行交换
		System.out.println(Collections.max(list));//输出list中的最大键值对
		System.out.println(Collections.min(list));
		Collections.replaceAll(list,"b","bb");//使用新值替换list对象的所有旧值
		List<Student> stu = new ArrayList<Student>();
		Student s1 = new Student(14,"张三");
		Student s2 = new Student(11,"等等");
		Student s3 = new Student(12,"画画");
		stu.add(s1);
		stu.add(s2);
		stu.add(s3);
		Student ss = Collections.max(stu,new Student());
		COllections.sort(stu,new Student());	
	}
}
class Student implements Comparetor<Student>{
	private int age;
	private String name;
	public Student(){}
	public Student(int age,String name){
		this.age = age;
		this.name = name;
	}
	@Override
	public int compare(Student o1,Student 02){//正序排列
		if(o1.age>o2.age) return 1;
		else if(o1.age>o2.age) return -1;
		else return 0;
	}
}
//synchronizedXxxx()方法可解决线程安全问题,eg:synchronizedList()

7.泛型

public class Test{
	public static void main(String[] args){
		A<String> a1 = new A<String>();//在new A的对象指定泛型的类型String
		a1.setKey("xxx");//对象使用setKey(T key)方法,中的key形参就是String
		String s = a1.getKey();//T getKey(),返回值就有new对象确定返回值是String
		B1<Object> b1 = new B1<Object>();
		B1<String> b2 = new B1<String>();
		B2 b3 = new B2();

		Cc<Object> c = new Cc<Object>();
		c.test("xxxx");
		//泛型方法,在调用之前没有固定的数据类型
		//在调用时,传入的参数是什么类型,就会把泛型改成什么类型
		Integer i = c.test4(2);//传递的参数为Integer
		Boolean b = c.test4(true);
	}
}
/**
*此处的泛型T可以任意取名,A,B,D
*一般使用T,意为type
*/
class A<T>{
	private T key;
	public void setKey(T key){
		this.key = key;
	}
	public T getKey(){
		return this.key;
	}	
}
//--------------------------------------------------
interface IB<T>{
	T test(T t);
}
/* 为传入泛型实参时,与泛型类的定义相同,在声明类时,需将泛型的声明一起加到类中*/
class B1<T> implements IB<T>{
	@Override
	public T test(T t){
		return t;
	}
}
/* 如果实现接口时指定接口的泛型的具体数据类型
*这个类实现接口所有方法的位置都要泛型替换实际的具体数据类型
*/
class B2 implements IB<String>{
	@Override
	public String test1(String s){
		return s;
	}
}
class Cc<E>{
	private E e;
	//静态方法的泛型方法
	public static <T> void test2(T t){
		//在静态方法中不能使用类定义泛型,只能使用静态方法自己定义的泛型
	}
	//无返回值的泛型方法
	public <T> void test3(T s){
		//在类上定义的泛型,可以在普通方法里使用
		T t = s;
	}
	//有返回值的泛型方法
	public <T> T test4(T s){
		return s;
	}
	//形参为可变参数的泛型方法
	public <T> void test5(T... strs){
		for(T s:strs){
			System.out.println(s);
		}
	}
}

8.有限制的通配符

public class Test{
	public static void main(String[] args){
		Dd d = new Dd();
		List<String> ls = new ArrayList<String>();
		d.test(ll);
		List<C1> lc = new ArrayList<C1>();	
		d.test1(lc);
		List<D1> ld = new ArrayList<D1>();	
		List<A1> la = new ArrayList<A1>();	
		d.test1(ld);
		d.test2(lc);
		d.test2(la);
	}
}
class Dd{
	public void test(List<?> list){}//test方法需要一个list集合参数,不确定list集合存储的类型
	public void test1<List<? extends C1> list){}//list参数的元素数据类型是C1及其子类
	public void test2<List<? super C1> list){}//list参数的元素数据类型是C1及其父类
	public void test3(List<? extends IA> list){}//list参数的元素类型是IA的实现类
}
class A1{}
class B1 extends A1{}
class C1 extends B1{}
class D1 extends C1{}
interface IA{}
class IAImpl implements IA{} 

9.实现接口的枚举类

public class Test{
	public static void main(String[] args){
		//Season.SPRING,这段执行就是获取一个Season的对象
		Season spring = Season.SPRING;
		spring.shouInfo();
		Season summer = Season.SUMMER;
		summer.showInfo();
		Season spring 1= Season.SPRING;
		//枚举类是单例模式=
		System.out.println(spring.equals(spring1));//true
	}
}
enum Season{
	SPRING("春天","春暖花开");//此处相当于在调用有参的私有构造
	SUMMER("夏天","炎炎夏日");
	AUTUMN("秋天","秋高气爽");
	WINTER("冬天","寒风刺骨");
	private final String name;
	private final String desc;
	private Season(String name,String desc){
		this.name = name;
		this.desc = desc;
	}
	public void shouInfo(){
		System.out.println(this.name+":"+this.desc);
	}
}	
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值