Java容器之Collection、List、Map等集合

容器的概念

如果并不知道程序运行时会需要多少对象,或者需要更复杂的方式存储对象,可以使用Java集合框架
Java集合框架包含的内容
在这里插入图片描述

容器API

Collection接口

Collection接口常用方法

  1. Collection子类可以存储不同类型的数据
  2. 默认长度是10,容量不够时将自动扩容1.5倍
    Collection接口常用方法
public class CollectionDemo{
	public static void main(String[] args){
		Collection collection = new ArraryList();
		collection.add(1);//add必须传入Object对象,因此1自动装箱成包装类
		collection.add(true);//同上
		collection.add(1.23);
		collection.add("abc");
		System.out.println(collection);
		((ArrayList)collection).add(1,"some");//强制转换在第1个位置添加“some”
		System.out.println(collection);
		Collection collection1 = new ArrayList();
		collection1.add("a");
		collection1.addAll(conllection);//添加另外一个集合
		collection1.clear();//清空集合中的元素
		collection.contains("abc");//判断集合中是否包含指定元素
		collection.contaninsAll(collection1);//判断是否包括另外一个集合
		collection.isEmpty();//判断是否为空
		collection.remove("abc");//删除指定元素
		collection.retainAll(collection1);//判断一个集合是否拥有另外一个集合的所有元素
		collection.size();//返回集合大小
		Object[] object = collection.toArray();//collection.toArray().var+回车自动补全类型,toArray()将集合转换为数组返回
		
	}
}

List接口

  1. List接口存储一组元素不唯一但有序(插入顺序有先后)的对象
  2. List继承了Collection所以大部分方法重写于Collection

ArraryList
ArratyList实现了长度可变的数组,在内存中分配连续的空间
优点:遍历和查询速度快
缺点:添加删除速度慢

List list = new ArrayList();
list.add("a");
list.add(1);
list.add("a");
list.add(true)
list.indexOf("a")//从头到位找一个“a”返回所在位置下标
list.lastIndexOf("a")//从后开始找
list.set(0,"haha")//指定位置插入元素
List list2 = list.subList(0,2);//截取0~2的元素返回新List
List list3 = List.of(1,2,3,4);//创建新List的一种方法,jdk12后添加

LinkedList

  1. LinkedList采用链表的存储方式
  2. 优点:插入删除效率高
    缺点:查询效率低
LinkedList linkedList = new LinkedList();
linkedList.add(123);//尾部插入后返回true
linkedList.add(0,"abc");
linkedList.addFirst(false);//头部插入
linkedList.addLast("hhh");//尾部插入无返回值
linkedList.element();//获取第一个元素
linkedList.size();//获取大小

Vector
Vector用法大致同ArrayList

  1. 也是List接口的一个子类实现
  2. 与ArrayList一样是数组
  3. ArrayList线程不安全,效率高。Vector线程安全,效率低
  4. ArrayList进行扩容是原来大小乘1.5倍,Vector扩容是原来的两倍

Iterator接口

1.迭代器接口,多用于增强for循环
2.在所有的集合类中都默认实现了Iterable接口,因此可以用foreach进行遍历
3.在iterator的方法中,要求返回一个Iterator的接口子类实例对象
此接口包含:hasNext()、next()等方法
4.增强for实际上使用了iterator接口
5.对集合的元素进行增加或删除操作时必须用对应集合下的Iterator内部类实例化对象进行操作
Iterator

ArrayList list = new ArraryList();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
//迭代器
Iterator iterator = list.iterator();//返回集合内实现了Iterator接口的内部类实例化对象

while(iterator.hasNext()){
	System.out.println(iterator.next());
}

for(Object i:list){//foreach
	System.out.println(i);
}

ListIterator

ArrayList list = new ArraryList();
list.add(1);
list.add(2);
list.add(3);
list.add(4);

ListIterator iter = list.listIterator();
while(iter.hasNext()){
	Object o = iterator.next();
	if(o.equals(1)){
		iter.remove();//使用对应类的内部类迭代器实例化对象进行元素删除
	}
	System.out.println(o);
}
//--------------
//向前遍历
while(iterator.hasPrivious()){
	System.out.println(iterator.previous());
}

list.contains()

List list = new ArrayList();
Person p1 = new Person("zhangsan",13)//假设有个Person类,该类有两个成员变量
Person p2 = new Person("lisi",11)
Person p3 = new Person("lisi",16)
list.add(p1);
list.add(p2);
//没重写对象的equals()和hashCode()方法前
System.out.print(list.contains(p3));//false比较地址值
//重写对象的equals()和hashCode()方法后
System.out.print(list.contains(p3));//true比较对象的hash值

Set接口

1.存储一组元素唯一,但无序的对象,操作数据的方法与List类似
2.Set不存在get()方法

Set set = HashSet();//同样实例化子类对象
set.add("123");
set.add(1);
set.add(true);
set.add("123")//元素重复,不会重复添加

HashSet

  1. 用HashMap实现
  2. 采用Hashtable存储结构
  3. 优点:添加查询删除速度快
    缺点:无序
  4. LinkedHashSet:采用哈希表存储结构,但同时用链表维护次序,因此有序
    可以存储任意类型数据

TreeSet
1.采用二叉树(红黑树)存储结构
2. 优点:有序,查询速度比List快
缺点:速度次于HashSet
3. 必须存储同类型的数据
4. 元素间的比较需要实现Comparable接口

与list的contains()原理相同,Set添加元素时比较是否有相同元素在未重写equals()和hashCode()方法时比较的是元素地址,在重写equals()和hashCode()方法后先比较hash值再用equals()进行比较

Comparable接口

使用需要进行元素比较的数据集合需要实现Comparable接口

TreeSet

  1. 所有可以排序的类都实现了java.lang.Compatable接口
  2. 实现了Comparable接口的类通过实现comparaTo方法从而确定该类对象的排序方式

内部比较器:

  1. compataTo定义在元素的类中,该元素的类实现Comparable接口的方式成为内部比较器
public class Person implements Comparable{
	public Person(string name,int age)
	{
		//...
	}
	public int comparaTo(Object o){
		Person p = (Person) o;
		if(//...){
			//...
			return 1;//this大于o
		}else if(//...){
			return -1;//this小于0
		}else{
			return 0;//等于
		}
	}
}

外部比较器

  1. 需要继承Comparator接口实现compare方法
  2. 定义在使用集合的类中,且集合所存储的元素类外(元素对象所属类的外部,其他类中)的比较器称为外部比较器,需要把比较结果传递到集合中
  3. 外部比较器可以定义成一个工具类,供其他需要进行比较的类使用
  4. 内部比较器和外部比较器同时存在优先使用外部比较器
public class SetDemo implements Comparator<Person>{//Comparator<Person>为泛型写法,具体参考介绍泛型的文章
	TreeSet treeSet = new TreeSet(new SetDemo());
	treeSet.add(new Person("lisi",11));
	treeSet.add(new Person("libai",20));
	public int compare(Person p1,Person p2){
		if(//...){
			//...
			return 1;//this大于o
		}else if(//...){
			return -1;//this小于0
		}else{
			return 0;//等于
		}
	}
}

Map接口

HashMap

  1. 用数组+链表+红黑树的结构存储
  2. 特点key-value映射
  3. 创建HashMap对象时并未分配数组空间,在使用put方法时创建并分配数组空间
  4. 构造方法可传入初始空间大小,必须大于0,但用put方法往里面插入数据时,初始大小会转为大于构造方法传入数值的最小 2 n 2^n 2n,如11转为 2 4 = 16 2^4=16 24=16,但允许传入大小不超过 2 30 2^{30} 230
  5. 也可传入扩容因子,默认为0.75,如果已使用空间大于长度的0.75则会进行扩容,扩容为长度*2,因此扩容后大小也为2的幂次
  6. 第4条会把数组长度限定在 2 n 2^n 2n次方大小,长度减1后的二进制数全为1,取全1的个数为位数,以此作为基础后,HashMap存放元素位置的计算方式为:用key的哈希值高16位与低16位进行位异或后,与前面的位数进行位与(高于 位数 的位会被丢弃) 后转为10进制则为元素散列后存放的位置(此条不一定准确,不同jdk散列方法也不一定一致,上述方法被称为扰动函数)
  7. 从上面几点可以看出,强制为 2 n 2^n 2n大小仅仅是为了方便进行散列找出元素存放位置,以及快速存取元素和减少hash冲突,且位运算通常比取模运算速度快,扩容时转移旧的table到新table时将按新的table长度来重新计算散列位置
  8. 位置冲突的元素会以链表或红黑树的数据结构进行存储(jdk1.8前为纯链表,1.8之后为链表长度大于等于7则把链表转换为红黑树,定为7是因为通过泊松分布进行统计后得出来的结论,如果长度小于等于6时时间复杂度相差不多,大于8时相差较大,所以取8),不扩容但冲突时链表插入使用尾插法,扩容转移时链表的先后顺序会倒转过来,是因为转移时链表的插入方式为头插法

HashMap常用方法:

Map<String,Integer> map = new HashMap<String,Integer>();
map.put("a",1);
map.put("b",2);
System.out.print(map);
System.out.print(map.isEmpty());
System.out.print(map.size());
System.out.print(map.containsKey("a"));
System.out.print(map.containsValue(2));
System.out.print(map.get("a"));
map.remove("a");
map.clear();//清空操作

//遍历操作
Set<String> keys = map.keySet();
for(String key:keys){
	System.out.print(map.get(key));
}

Collection<Integer> values = map.values();
for(Integer v:values){
	System.out.print(v);
}

//迭代器
Set<String> keys2 = map.ketSet();
Iterator<String> iterator = key2.iterator();
while(iterator.hasNext()){
	String key = iterator.next();
	System.out.print(map.get(key));
}

Map是java中的接口,Map.Entry是Map的一个内部接口。

Map提供了一些常用方法,如keySet()、entrySet()等方法,keySet()方法返回值是Map中key值的集合;entrySet()的返回值也是返回一个Set集合,此集合的类型为Map.Entry。

Map.Entry是Map声明的一个内部接口,此接口为泛型,定义为Entry<K,V>。它表示Map中的一个实体(一个key-value对)。接口中有getKey(),getValue方法。

HashMap的内部Entry类(jdk1.8开始为Node)实现了Map.Entry接口

用Entry进行遍历

//Map.entry
Set<Map.Entry<String,Integer>> entries = map.entrySet();
Iterator<Map.Entry<String,Integer>> iter1 = entries.iterator();
while(iter1.hasNext()){
	Map.Entry<String,Integer> next = iterator.next();
	System.out.print(next.getKey()+" "+next.getValue());
}

HashMap与HashTable:
Map与Table用法类似
HashMap线程不安全,效率高,key value都可以为null
HashTable线程安全,效率低,key value不允许为null

LinkedHashMap
用链表结构存储
有序的HashMap 速度快
TreeMap
用红黑树结构存储
有序 速度没有HashMap快

Set与Map区别
Set没有key,Map以key作为索引存储value

Collections工具类

Collections提供静态方法,可以对Collection及其子类集合进行排序、查找、替换等操作

List<String> list new ArraryList<String>();
list.add("a");
list.add("bn");
list.add("cvb");
list.add("dfgh");

Collections.addAll(list,"erty","fghj","ghjkl");//addAll可以用于给集合添加元素,addAll为参数个数不定的函数
list.sort(new Comparator<String>(){//匿名内部类自定义外部比较器
	@Override
	public int compare(String o1,String o2){
		if(o1.length()<o2.length()){
			return -1;
		}else if(o1.length()>o2.length()){
			return 1;
		}
		else{
			return 0;
		}
	}
});

Collections.sort(list);//排序

Collections.sort(list,new Comparator<String>(){//匿名内部类自定义外部比较器
	@Override
	public int compare(String o1,String o2){
		if(o1.length()<o2.length()){
			return -1;
		}else if(o1.length()>o2.length()){
			return 1;
		}
		else{
			return 0;
		}
	}
});

Collections.binarySearch(list,"bn");//排序后才能使用的二分查找

Collections.fill(list,"haha");//替换所有元素为哈哈
Collections.shuffle();//随机排序
Collections.reverse();//逆序

Arrarys

数组操作工具类,提供集合和数组之间的转换

List<Integer> ints = Arrays.asList(1,2,3,4,5);
Object[] object = ints.toArrays();

集合总结

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值