【Java基础22】集合的各个接口实现

集合

1、Collection接口

Collection层次结构中的根接口。Collection表示一组对象,这些对象也称为collection的元素。一些collection允许有重复的元素,而另一些则不允许。一些collection是有序的,而另一些则是无序的。JDK不提供此接口的任何直接实现:它提供更具体的子接口(如Set和List)实现。此接口通常用来传递collection,并在需要最大普遍性的地方操作这些collection。

2、List接口

List接口是有序的collection,此接口的用户可以对列表中每个元素的插入位置进行精确的控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。

ArrayList:

(1)实现原理,采用动态对象数组实现,默认构造方法创建了一个空数组。

(2)第一次添加元素,扩展容量是10,之后的扩充算法:原来数组大小+原来数组的一半。

(3)不适合进行删除或插入操作。

(4)为了防止数组动态扩充次数太多,建议创建ArrayList时,给定初始容量。

(5)线程不安全,适合在单线程访问时使用。

Vector:

(1)实现原理,采用动态对象数组实现,默认构造方法创建了一个大小为10的对象数组。

(2)扩充算法:当增量为0时,扩充为原大小的2倍,当增量大于0时,扩充为原来大小+增量。

(3)不适合进行删除或插入操作。

(4)为了防止数组动态扩充次数太多,建议创建ArrayList时,给定初始容量。

(5)线程不安全,适合在多线程访问时使用,效率较低。

LinkedList:

(1)实现原理,采用双向链表结构实现。

(2)适合插入,删除操作,性能高。

在实际开发中,如何选择list的具体实现?

(1)安全性问题:Vector/ArrayList

(2)是否频繁插入,删除操作:LinkedList

(3)是否存储后遍历:ArraysList

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

public class Test01 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		arrayList();

	}
	
	 private static void arrayList(){
		 List<String> list=new ArrayList<>();//只计算String类型
			list.add("1");
			list.add("2");
			list.add("3");
			list.add("4");
//			list.add(10,null);
			int size=list.size();
			for(int i=0;i<size;i++){
				System.out.println(list.get(i));
			}
			System.out.println(list.contains("1"));//判断是否包含“1”
			list.remove("2");//删除
			System.out.println(list.size());//输出list大小
			String[] array=list.toArray(new String[]{});//转为String类型
			for(String x:array){
				System.out.println(x);
			}
	 }
    
     private static void vector(){
		 Vector<String> v=new Vector<>();//只计算String类型
			v.add("1");
			v.add("2");
			v.add("3");
			v.add("4");
			int size=v.size();
			for(int i=0;i<size;i++){
				System.out.println(v.get(i));
			}
			
	 }
    
    private static void linkedList(){
		LinkedList list=new LinkedList();
		list.add("1");
		list.add("2");
		list.add("3");
		list.add("4");
		int size=list.size();
		for(int i=0;i<size;i++){
			System.out.println(list.get(i));
		}
	}

}



3、Set接口

无序、一个不包含重复元素的collection,并且最多包含一个null元素。

HashSet:

(1)实现原理,基于哈希表(HashMap)实现。

哈希表的存储结构:数组+链表,数组里的每个元素以链表的形式存储。

把对象存储到哈希表中,先计算对象的HashCode值,再对数组的长度求余数,来决定对象要存储在数组中的哪个位置。

(2)不保证顺序恒久不变。

(3)添加元素时,把元素作为HashMap的Key存储,HashMap的value使用一个固定的object对象。

(4)排除重复元素,通过equals检查对象是否相同。

(5)在Java集合中判断两个对象是否相等的规则是:

判断两个对象的HashCode是否相等,不相等结束,相等转入2

判断两个对象用equals运算是否相等,不相等结束,相等则认为两个对象相等。

(6)自定义对象要认为属性值相同时为同一个对象,则需要重写所在对象的类的HashCode和equals方法。

import java.util.*;
public class Test02 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
//		hashSet();
		pet();
	}
	
	private static void hashSet(){
		Set<String> set=new HashSet<>();
		set.add("1");
		set.add("2");
		set.add("3");
		set.add("4");
		set.add("3");
		String[] str=set.toArray(new String[]{});
		for(String x:str){
			System.out.println(x);
		}
		System.out.println(set.size());
	}
	
	private static void pet(){
		Pet pet1=new Pet("11",1);
		Pet pet2=new Pet("22",1);
		Pet pet3=new Pet("33",1);
		Pet pet4=new Pet("44",1);
		
		Set<Pet> set=new HashSet<>();
		set.add(pet1);
		set.add(pet2);
		set.add(pet3);
		set.add(pet4);
		set.add(pet3);
		
		System.out.println(set.size());
		System.out.println(pet1.hashCode());
		System.out.println(pet2.hashCode());
		System.out.println(pet3.hashCode());
		System.out.println(pet4.hashCode());
		
	}
	

}

class Pet{
	private String name;
	private int age;
	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 "Pet [name=" + name + ", age=" + age + ", getName()=" + getName() + ", getAge()=" + getAge()
				+ ", getClass()=" + getClass() + ", hashCode()=" + hashCode() + ", toString()=" + super.toString()
				+ "]";
	}
	public Pet(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public Pet() {
		super();
		// TODO Auto-generated constructor stub
	}
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + age;
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Pet other = (Pet) 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;
	}
	
	
}

TreeSet:

有序的,基于TreeMap(二叉树数据结构),对象需要比较大小,通过对象比较器来实现。

对象比较器还可以用来去除重复元素,如果自定义的数据类,没有实现比较器接口,将无法添加到TreeSet集合中。

private static void TreeSet(){
		TreeSet<Pet> ts=new TreeSet<>(new PetComparator());//比较器可以判断重复还可以排序
		Pet pet1=new Pet("11",1);
		Pet pet2=new Pet("22",3);
		Pet pet3=new Pet("33",2);
		Pet pet4=new Pet("44",1);
		ts.add(pet1);
		ts.add(pet2);
		ts.add(pet3);
		ts.add(pet4);
		System.out.println(ts.size());//按照年龄比较,输出1
		for(Pet p:ts){
			System.out.println(p);
		}
	}

class PetComparator implements Comparator<Pet>{
	@Override
	public int compare(Pet o1, Pet o2) {
		// TODO Auto-generated method stub
		return o1.getAge()-o2.getAge();
	}
	

LinkedHashSet:

哈希表和链接列表实现,维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,即按照元素将元素插入到set的顺序进行迭代。

private static void LinkedHashSet(){
		LinkedHashSet<Pet> lhs=new LinkedHashSet<>();
		Pet pet1=new Pet("11",1);
		Pet pet2=new Pet("22",3);
		Pet pet3=new Pet("33",2);
		Pet pet4=new Pet("44",1);
		lhs.add(pet1);
		lhs.add(pet2);
		lhs.add(pet3);
		lhs.add(pet4);
		System.out.println(lhs.size());//按照年龄比较,输出1
		for(Pet p:lhs){
			System.out.println(p);
		}
	}

在实际开发中,如何选择Set的具体实现?

如果要排序,选择TreeSet

如果不需要排序,也不用保证顺序,选择HashSet

如果不需要排序,要保证顺序,选择LinkedHashSet

4、Iterator/Enumeration/foreach接口

遍历集合的方式。

//Iterator
public static void main(String[] args) {

		Pet pet1=new Pet("11",1);
		Pet pet2=new Pet("22",3);
		Pet pet3=new Pet("33",2);
		Pet pet4=new Pet("44",1);
		
		List<Pet> list=new ArrayList<>();
		list.add(pet1);
		list.add(pet2);
		list.add(pet3);
		list.add(pet4);
		iterator(list);
	}
	
	public static void iterator(Collection c){
		Iterator<Pet> i=c.iterator();
		while(i.hasNext()){
			System.out.println(i.next());
		}
	}


//Enumeration
	public static void enumeration(){
		Vector<Pet> v=new Vector();
		Pet pet1=new Pet("11",1);
		Pet pet2=new Pet("22",3);
		Pet pet3=new Pet("33",2);
		Pet pet4=new Pet("44",1);
		v.add(pet1);
		v.add(pet2);
		v.add(pet3);
		v.add(pet4);
		Enumeration<Pet> em=v.elements();
		while(em.hasMoreElements()){
			System.out.println(em.nextElement());
		}
	}

//foreach
public static void foreach(){
		List<Pet> list=new ArrayList<>();
		Pet pet1=new Pet("11",1);
		Pet pet2=new Pet("22",3);
		Pet pet3=new Pet("33",2);
		Pet pet4=new Pet("44",1);
		list.add(pet1);
		list.add(pet2);
		list.add(pet3);
		list.add(pet4);
		list.forEach((Pet p)->{System.out.println(p);});//Consumer<T>
   		list.forEach(System.out::println);
	
	}

5、JDK1.8新特性

Consumer 消费者接口

Function<T,R> 表示接受一个参数并产生结果的函数

Supplier 代表结果供应商

Predicate 断言接口

Stream接口

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class Test03 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Stream<String> stream=Stream.of("day","day","up","up");
//		stream.forEach((str)->{System.out.println(str);});
//		stream.forEach(System.out::println);
		
//		stream.filter((s)->s.length()>2).forEach(System.out::println);//过滤
		
//		stream.distinct().forEach((s)->System.out.println(s));//去除重复
		
//		stream.map(s->s.toUpperCase()).forEach(System.out::println);;//转为大写输出
		
//		Stream<List<Integer>> ss=Stream.of(Arrays.asList(1,2,3),Arrays.asList(4,5));//添加
//		ss.flatMap(list->list.stream()).forEach(System.out::println);;
		 
//		Optional<String> opt=stream.reduce((s1,s2)->s1.length()>s2.length()?s1:s2);
//		System.out.println(opt.get());
		
		List<String> list=stream.collect(Collectors.toList());
		list.forEach(s->System.out.println(s));
	}

}

6、Map接口

将键映射到值。键值对存储一组对象,Key不能重复,Value可以重复。具体的实现类:HashMap、TreeMap、HashTable、LinkedHashMap

HashMap的实现原理:

(1)基于哈希表(数组+链表+红黑树)。

(2)默认加载因子为0.75,默认数组大小是16。

(3)如何把对象存储到哈希表中?

把Key对象通过Hash()方法计算hash值,然后用这个hash值对数组长度取余数(默认16),来决定该Key对象在数组中存储的位置,当这个位置有多个对象时,以链表结构存储,JDK1.8之后,当链表长度大于8时,链表将转换为红黑树结构存储。这样的目的,是为了取值更快,存储的数据量越大,性能的表现越明显。

(4)扩充原理: 当数组的容量超过了75%,那么该数组需要扩充。

**(5)扩充算法: **当前数组的容量<<1(相当于乘2),扩大1倍,扩充次数过多,会影响性能,每次扩充表示哈希表重新散列(重新计算每个对象的存储位置),我们在开发过程中尽量要减少扩充次数带来的性能问题。

(6)线程不安全,适合在单线程中使用。

//HashMap
import java.security.*;
import java.util.*;
import java.util.Map.Entry;
public class Test01 {
//Map
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Hashmap();
	}
	
	private static void Hashmap(){
		Map<Integer,String> map=new HashMap();
		map.put(1, "一");
		map.put(2, "二");
		map.put(3, "三");
		map.put(4, "四");
		System.out.println(map.size());
		System.out.println(map.get(2));//根据键取值
		
		Set<Entry<Integer,String>> entry=map.entrySet();
		for(Entry e:entry){
			System.out.println(e.getKey()+"->"+e.getValue());//遍历1
		}
		
		Set<Integer> keys=map.keySet();
		for(Integer i:keys){
			String str=map.get(i);
			System.out.println(i+"->"+str);//遍历2
		}
		
		Collection<String> values=map.values();
		for(String str:values){
			System.out.println(values);//遍历3,只遍历值
		}
		
		map.forEach((key,value)->{System.out.println(key+"->"+value);});//遍历4
	}

}

Hashtable:

(1)基于哈希表实现(数组+链表)。

(2)默认数组大小为11,加载因子0.75。

(3)扩充方式:原数组大小<<1+1。

(4)线程安全,适合多线程使用。

private static void Hashtable(){
		Map<Integer,String> m=new Hashtable();
		m.put(1, "一");
		m.put(2, "二");
		m.put(3, "三");
		m.put(4, "四");
		m.forEach((key,value)->{System.out.println(key+"->"+value);});
		
	}

LinkedHashMap:

LinkedHashMap是HashMap的子类,由于HashMap不能保证顺序恒久不变,此类使用一个双重链表来维护元素添加的顺序。

使用方法参考Hashtable

TreeMap:

基于二叉树的红黑数实现,有序。

JDK1.8新特性
private  static void hashmap(){
		Map<Integer,String> map=new HashMap();
		map.put(1, "11");
		map.put(2, "22");
		map.put(3, "33");
		String str=map.getOrDefault(3, "null");//不需另外判断是否为空
		System.out.println(str);
		
		map.putIfAbsent(3, "333");//若key=3为空则填充
		map.forEach((key,value)->{System.out.println(value);});
		
		map.replace(1, "111");//替换key=1的value
		System.out.println(map.get(1));
		
		map.compute(1, (k,v)->v+"1");//在key=1的value后拼接一个“1”
		System.out.println(map.get(1));
		
		map.merge(1, "23", (oldVal,newVal)->newVal.concat(oldVal));//拼接新的内容,key不存在就直接填入新的value
		System.out.println(map.get(1));
	}

7、Collections工具类

private static void list(){
		List<String> l=new ArrayList();
		l.add("1");
		l.add("2");
		l.add("3");
		l.add("4");
		l.add("5");
		Collections.reverse(l);//翻转
		Collections.shuffle(l);//打乱顺序
		Collections.sort(l);//排序
		Collections.swap(l, 1, 2);//交换
		Collections.rotate(l, 2);//旋转
		System.err.println(Collections.binarySearch(l, "3"));
		System.out.println(Collections.frequency(l, "1"));
		Collections.replaceAll(l, "4", "6");
		
		List<String> synlist=Collections.synchronizedList(new ArrayList<String>());//线程同步
		
		List<String> elist=Collections.emptyList();//return一个空集合,避免空指针
		
	}

8、Optional容器类

private static void optional(){
		//创建Optional对象
		Optional<String> opt=Optional.of("opt");
		Optional<String> opt1=Optional.empty();
		Optional<String> opt2=Optional.ofNullable("opt");
		
		System.out.println(opt.isPresent());//判断空指针
		System.out.println(opt.get());//输出
		
		opt1.ifPresent((value)->System.out.println(value));//若存在值就返回,没值不返回
		System.out.println(opt1.orElse("null"));//无值返回null
		
//		try {
//			opt1.orElseThrow(Exception::new);//不存在则抛出一个异常
//		} catch (Exception e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
		
		Optional o=opt.map((value)->value.toUpperCase());//使用mapping方法
		System.out.println(o);
		
		opt=opt.flatMap((value)->Optional.of(value.toUpperCase()+"flatMap"));
		System.out.println(opt.orElse("null"));
		
		opt.filter((value)->value.length()>1);
	}


9、Queue(队列)、Deque(双端队列)接口、Stack(栈)类

LinkedList实现了Queue接口

	private static void queue(){
		Queue q=new LinkedList();
		q.add("1");
		q.add("2");
		q.add("3");
		q.add("4");
		System.out.println(q.size());
		System.out.println(q.peek());//队头
		System.out.println(q.size());
		System.out.println(q.poll());//出队
		System.out.println(q.size());
	}

LinkedList实现了Deque接口

	private static void deque(){
		Deque<String> d=new LinkedList<>();
		d.add("1");
		d.add("2");
		d.add("3");
		d.add("4");
		System.out.println(d.getFirst());//队头
		System.out.println(d.getLast());//队尾
	}

Stack类

private static void stack(){
		Stack<String> s=new Stack<>();
		s.push("1");
		s.push("2");
		System.out.println(s);
		s.pop();
		System.out.println(s);
	}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值