Java集合讲解(List&Set)

1. 性能比较高效的几个集合
Collection 、List、Set、Map、Enumeration、Queue、ListIterator。

2. Collection 最大的单父接口集合.

  • 常用的API
boolean	add​(E e)	 确保此集合包含指定的元素(可选操作)。
Iterator<E>	iterator​()	 返回对此集合中的元素进行迭代的迭代器。

在jdk1.5以后基本都是使用的collection的2个子类(list)和(set)
在这里插入图片描述
api文档

3. List 子接口集合(允许重复)

  • List中扩充的的方法
    E get​(int index) 返回此列表中指定位置的元素。
    E set​(int index, E element) 用指定的元素替换此列表中指定位置的元素(可选操作)。
    ListIterator listIterator​() 返回此列表中的元素的列表迭代器(按适当顺序)。
  • List子接口中存在的3个实现子类 1.ArrayList 2.linkedList 3.Vector
    在这里插入图片描述
  • ArrayList
    List特征
  1. 保存的顺序就是器存储的顺序
  2. List里面允许有 重复的数据
  3. 在jdk1.8以后在Iterable父接口中定义了一个方法foreach(),方法的使用如下:
    输出支持:default void forEach(Consumer<? super T> action);
    使用案例:
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
List<String> all = new ArrayList<String>() ; // 为List父接口进行实例化
		all. add("Hello") ;
		all.add("Hello") ; // 重复数据
		all. add("World") ;
		all. add( "MLDN") ;
	all. forEach((str)->{
	System. out. print(str + "、");
	});
}
  • ArrayList分析(通过类的构造名称就可以发现了,ArrayList应该是一个封装的数组)
    ArrayList里面多包含的是实际上就是一个对象数组,如果现在在进行数据追加的时候发现得了数组的长度不够的时候,这个时候就会开辟新的数组,同时将旧的数组内容拷贝到一个新的数组中(在这个新的数组大小的位置还要进行一个数据的操作比较以下代码:
private int newCapacity(int minCapacity) {
	// overflow- conscious code
	int oldCapacity = elementData .length;
	int newCapacity = oldCapacity + (oldCapacity >> 1);
	if (newCapacity . minCapacity <= e) {
	if (elementData == DEFAUL TCAPACITY_ EMPTY_ ELEMENTDATA)
	return Math. max(DEFAULT CAPACITY, minCapacity);
	if (minCapacity <0) // overflow
	throw new OutOfMemoryError();
	return minCapacity; .
	}
	return (newCapacity - MAX_ ARRAY_ SIZE <=0)
? newCapacity
: hugeCapacity(minCapacity);
}
private static int hugeCapacity(int minCapacity) {
	if (minCapacity < 0) // overflow
	throw new OutOfMemoryError();
	return (minCapacity > MAX_ ARRAY_ SIZE)
	? Integer . MAX_ VALUE
	: MAX_ ARRAY_ SIZE ;
}

根据新增加的长度的大小原来的数据进行比较,那个值大,就开辟此长度大小的数组长度

JDK1.9之后:ArayList默认的构造只会使用默认的空数组,使用的时候才会开辟数组,默认的开辟大小为10的数组
JDK1.9之前:。ArrayList默认的构造实际上就会默认开辟大小为10的数组。

  • 分析:
    如果在实例化ArrayLsit类对象的时候并没有传递初始化的长度,则默认的情况下会使用一个空的数组,但是如果在数据在进行增加的时候,发现了数组的长度不够的时候,则会判断当前增长的容量和默认的大小容量进行比较大小,则会使用较大的数进行新的数组开辟,所以可以得出:当ArrayList之中保存的容量不足的时候就会采用成倍的方式进行增长,原始长度为10,那么下次增长的是为20以此推出,如果在使用ArrayList的时候一定要估算你的数据量,如果你的数据量是10个以内的话,就使用无参构造,如果是大于10个 的话就使用有参数构造方法,因为拷贝操作会消耗一定的性能和垃圾;

  • 在使用List集合储存自定义的类的时候,一定要去重写equals方法(因为在删除数据和数据是否存在时候要进行比较方法)

public class ital06 {
	public static void main(String[] args) {
		List<person> list=new ArrayList<person>();
		list.add(new person("小胡",19));
		list.add(new person("小黑",19));
		list.add(new person("小白",19));
	}	
	}
class person{
	private String name;
	private int age;
	public person(String name,int age) {
		this.name=name;
		this.age=age;
	}
	//setget略
	@Override
	public String toString() {
		return "姓名:"+this.name+"年龄:"+this.age;
	}
	public boolean equlas(Object obj) {
		if(this==obj) {
			return true;
		}
		if(obj==null) {
			return false;
		}
		if(!(obj instanceof person)) {
			return false;
		}
		person11 per=(person)obj;
		return this.name==per.name && this.age==per.age;
	}
}
  • LinkedList子实现类
    结构图:
    在这里插入图片描述
    LinkedList是通过链表进行实现的一个集合
    观察LinkedList的add方法
    public boolean add(E e){
    llinkLast(e);
    return true;
    }

  • linkLast(e)代码

void linklast(E e) { 
	final Node<E> l = last;.
	final Node<E> newNode = new Node<>(l, e, null);
		last = newNode;
		if (l == nu1l)
			first = newNode;
		else
			l.next = newNode;
			size++;
			modCount++;
}
  • 分析:
    在L inkedList类里面保存的数据都是利用Node节点进行的封装处理,同时为了提高程序执行性能,每一-次都会保存上一个追加的节点(最后一个节点),就可以在增加数据的时候避免递归处理,在增加数据的时候要进行数据保存个数的追加。
    通过分析可以得出LinkList封装的就是一个链表实现;

  • linkedList和ArrayList的区别

  1. ArrayL ist是数组实现的集合操作,而LinkedI ist是链表实现的集合操作:。
  2. 在使用List集合中的get(方法根据索引获取数据时,ArrayList的时间复杂度为“O(1)”、而LinkedList的时间复杂度为O(n)(n为集合的长度);
    ArrayList 在使用的时候默认的初始化对象数组的大小长度为10, 如果空间不足则会采用2陪的形式进行增长,如果保存大数据量的时候有可能会造成垃圾的产生以及性能的下降,但是这个时候可以使用LinkedIist进行数据的保存;
  • Vector子实现类
    继承结构:
    在这里插入图片描述
    ArrayList 和vertor的之间的主要的区别是在于,vector里面的方法都是通过的synchronizeto同步修饰的,所在多线程访问的时候,ArrayList是一个不安全的,而vector是安全的,但是性能有所下降。
  • 分析:
    Vector类如果使用的是无参构造方法,则-定会默认开辟-一个 10个长度的数组,通过源代码的分析可以发现Vector类之中的操作方法采用的都是synchronized 同步处理,而ArrayList未使用,Vector类之中的方法在多线程访问的时候属于线程安全的,但是性能不如ArrayList高。

4. Set子接口集合(不允许重复)
set的基本结构图
在这里插入图片描述

  • Set接口中有2个常用的子类 1.HashSet 2.TreeSet
    注意:Set这个集合在存储的时候,如果出现的了重复的值的话会直接抛出异常(使用Set静态方法的时候)

  • HashSet子实现类(无序的)
    不允许保存重复的元素(Set)一样的,排序是无序的排序形式
    在这里插入图片描述

  • TreeSet 子实现类(有序的结构)
    继承结构:
    在这里插入图片描述
    当使用TreeSet的时候所保存的数据都是按照的数据的升序进行的自动排序的处理操作。

  • 自定义类TreeSet存储

  • 分析:
    在TreeSet中进行自定义的类的存储的时候,需要主要的是,这个时候TreeSet判断数据是否重复的过程是根据comparable去实现的,所以在存储一个自定义的类的数据的时候,一定要进行的是实现comparable接口,还需要注意的一点是,当如果有多个属性的时候,这个如果想要去进行比较的话,需要把所有的属性都进行比较,那么肯定会复杂,所以一般的情况下都是采用的HashSet进行的数据的存储的。

  • 案例代码

class student implements Comparable<student>{
	private String name;
	private int age;
	public student(String name,int age) {
		this.name=name;
		this.age=age;
	}
	@Override
	public int compareTo(student stu) {
		if(this.age<stu.age) {
			return -1;
		}else if(this.age>stu.age) {
			return 1;
		}
		return this.name.compareTo(stu);
	}
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return this.name+this.age;
	}
}
public class ital07 {
	public static void main(String[] args) {
		Set<student> set=new TreeSet<student>();
		set.add(new student("zhangsang",19));
		set.add(new student("lisi",19));
		set.add(new student("wanwu",19));
		set.add(new student("zhangsang",19));
		for (student student : set) {
			System.out.println(student.toString());
		}
	}
}
  • 分析重复元素的消除
    在TreeSet中使用的comparable实现的重复的判断,而在HashSet中判断元素的重复的方式并不是利用的Comparable接口完成的,它利用的是object中的2个方法进行是实现的

对象编码: public int hashCode();
对象比较: public boolean equals(Object obj);

  • 分析
    在进行重复元素的判断的时候,首先判断的是hashCode()编码的匹配,如果改编码不存在的话,就可以存储,如果该编码存在了,则进一步进行equals的方法比较,如果对象返回相同,则不能进行保存.所以在使用HashSet进行数据的存储的时候,需要进行重写HashCode方法和equals方法,判断数据的重复比较

Java中进行真正进行元素重复判断的就是使用的HashCode和equlas方法进行的,而也只有在TreeSet中才使用的是Comparable这个比较器进行的重复的判断的。

资料参考声明:部分图片来自于魔乐科技学习视频

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值