集合,List

集合
Collection 接口

  • Collection 是最基本的集合接口,一个 Collection 代表一组 Object,即 Collection 的元素, Java不提供直接继承自Collection的类,只提供继承于的子接口(如List和set)。
  • Collection 接口存储一组不唯一,无序的对象。

List 接口

  • List接口是一个有序的 Collection,使用此接口能够精确的控制每个元素插入的位置,能够通过索引(元素在List中位置,类似于数组的下标)来访问List中的元素,第一个元素的索引为 0,而且允许有相同的元素。
  • List 接口存储一组不唯一,有序(插入顺序)的对象。

Set

  • Set 具有与 Collection 完全一样的接口,只是行为上不同,Set 不保存重复的元素。
  • Set 接口存储一组唯一,无序的对象。
    在这里插入图片描述

继承体系

  • Java的集合类主要由两个接口派生而出:Collection和Map。Collection和Map是Java结合框架的根接口,这两个接口又包含了一些子接口或实现类。
  • 在这里插入图片描述在这里插入图片描述
    由以上两图我们可以看出Java集合类有清晰的继承关系,有很多子接口和实现类。但是,并不是所有子接口或实现类都是最常用的。
    下面我们列举出最常用的几个子接口和实现类:
    Collection ——> List ——> ArrayList类
    Collection ——> List ——> LinkedList类
    Collection ——> Set ——> HashSet类
    Collection ——> Set ——> SortedSet接口 ——> TreeSet类
    Map ——> HashMap类
    Map ——> SortedMap ——> TreeMap类

Collection

  • Collection接口是List接口和Set接口的父接口,它定义的方法可以用于操作List集合和Set集合。
    Collection接口定义的方法
    在这里插入图片描述

  • 集合中的方法,是所有子实现类都有的,那么我们先看看集合中都有什么

  • 集合中只能保存单一类型,并且只能保存引用,不能保存基本类型

  • 不过这个单一类型 是Object, 也就意味着,可以容纳所有类型的数据,因为任何数据都会向上转型为Object 如果是基本类型,会先自动装箱

  • 为对应的包装类,再向上转型,并且这些数据都会丢失特有属性

package Test;

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

public class Collection_01 {

	public static void main(String[] args) {
		// 创建一个ArrayList对象,由于多态,所以只能调用Collection中有的
		Collection c1 = new ArrayList();
		// 判断集合是否为空(长度为0,而不是null)
		System.out.println(c1.isEmpty());
		// int --> Integer --> Object
		// 添加
		c1.add(1);
		c1.add(14);
		c1.add("sdf");
		c1.add(12);
		c1.add(9);
		c1.add(1);

		// 已有元素个数
		System.out.println(c1.size());
		System.out.println(c1.isEmpty());
		// 判断是否存在, 会调用判断元素的equals方法,挨个和集合中的每个元素进行比较
		System.out.println(c1.contains(new Integer(12)));
		// 根据内容删除元素,用要删除的元素对象调用equals方法,挨个和集合中的元素进行比较
		// 如果找到 就删除,并返回true, 如果未找到 就return false
		// 移除第一个1
		c1.remove(1);
		System.out.println(c1);

		// 通过上面代码和看底层实现得知,会调用判断/删除对象的equals进行比较
		// 所以 当我们操作的是自定义类型的时候,就需要根据需求自己覆写equals方法
		// 如果使用的是Integer/String等对应的包装类的时候,则不需要,因为人家覆写了equals方法
		Student s1 = new Student(1, "ad", 18);
		Student s2 = new Student(1, "ad", 18);
		c1.add(s1);
		System.out.println(c1);
		System.out.println(c1.contains(s1));
		System.out.println(c1.contains(s2));
		System.out.println(c1.remove(s2));
		System.out.println(c1);

		// 清空集合
		c1.clear();
		System.out.println(c1);
		System.out.println(c1.size());
		System.out.println(c1.isEmpty());
		c1.add("张三");
		
		Object[] arr={1,2,3,4};
		//利用Arrays的asList 可以直接把数组转换为集合
		Collection c2=Arrays.asList(arr);
		// 把 c2集合中元素,全部添加到c1中
		c1.addAll(c2);
		System.out.println("c1"+c1);
		
		//转换为数组,无参,返回新数组
		Object[] objArr=c1.toArray();
		// 利用有参方式,也能转换为数组,返回值为传入的数组引用
		Object[] objArr2=new Object[c1.size()];
		// 由于是传引用 所以不用接收返回值
		c1.toArray(objArr2);
		for(Object object:objArr2){
			System.out.println(object);
		}
	}
}

class Student {
	private int id;
	private String name;
	private int age;

	@Override
	public boolean equals(Object obj) {
		if (obj == this) {
			return true;
		}
		if (obj instanceof Student) {
			Student s1 = (Student) obj;
			return this.id == s1.id;
		}
		return false;
	}

	public Student(int id, String name, int age) {
		super();
		this.id = id;
		this.name = name;
		this.age = age;
	}

	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	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;
	}

}

//
true
6
false
true
[14, sdf, 12, 9, 1]
[14, sdf, 12, 9, 1, Student [id=1, name=ad, age=18]]
true
true
true
[14, sdf, 12, 9, 1]
[]
0
true
c1[张三, 1, 2, 3, 4]
张三
1
2
3
4

Iterator

  • Iterator : 迭代器

  • 迭代器是一种模式,又称光标,他可以使对于序列类型的数据结构的遍历行为与被遍历的对象分离

  • 我们不需要关心该序列底层数据结构是什么样子的,只要拿到这个对象,使用迭代器就可以进行遍历这个集合对象

  • 生成迭代器

  • Iterator it = 集合对象.iterator();

  • 迭代器为了方便遍历,提供了三个方法

  • 1 boolean hasNext() : 判断光标的下一位是不是还有元素,有就是true,没有就是false

  • 2 E next() : 将迭代器光标向下移动一位,并取出该元素 Element

  • 3 remove() : 删除当前指向的元素

  • 迭代器一旦创建,集合不能进行添加和删除操作,如果 添加或删除了.必须重新生成迭代器

  • 增强for循环 forEach 就是为了让iterator循环访问的形式简单,写起来方便,但是也是不能进行添加和删除的

  • 使用普通的for和while是可以进行添加删除的,这种遍历还是和数据结构存储相关的

package Test;

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

public class Collection_02 {

	public static void main(String[] args) {
		Collection x = new ArrayList();
		x.add(4);
		x.add(2);
		x.add(3);
		x.add(1);
		//x.add("san");
		// 生成迭代器
		Iterator it = x.iterator();
		x.add(5);
		// 如果添加或删除了集合中的数据,则迭代器需要重新生成
		// it.next();
		it = x.iterator();
		
		//判断还有没有数据,有就执行
		while(it.hasNext()){
			// 光标向下移动一位,并取出数据
			Object e=it.next();
			System.out.println(e);
			//删除当前指向的元素(必须使用迭代器的删除,否则报错)
			it.remove();
		}
		System.out.println(x);
		// false 因为已经移动到最后了,此时想要继续使用必须重新生成
		System.out.println(it.hasNext());
	}

}

//
4
2
3
1
5
[]
false

注意: 使用contains和remove的时候 如果是自定义类型,需要根据需求覆写equals方法
因为这两个方法底层都会去自动调用对象的 equals方法来进行对象的比较

List

特性:

  • 有序,可重复
    有指定下标,添加顺序和取出顺序一致
  • ArrayList : 底层是个Object[] 数组,随机查询效率高,随机删除效率低,默认初始化时10,扩大之后是原来的1.5倍,并且是第一次添加数据的时候进行默认长度设置,只new的时候,不添加数据,则长度为0, 等于是 Object[] elementData= {}; 长度为0
  • LinkedList : 底层是双向链表,随机查询效率低,随机删除效率高
  • Vector : 已经过时,属于线程安全,而ArrayList是Vector的升级版 , 默认初始化是10,扩大之后是原来的2倍

ArrayList:

package Test;

import java.util.ArrayList;

public class Collection_03_Arraylist {

	public static void main(String[] args) {
		ArrayList list = new ArrayList();
		// 尾部添加
		list.add(1);
		list.add(2);
		list.add(5);
		// 添加到指定位置
		list.add(0, 8);
		// 更改指定元素的值
		list.set(1, 11);
		// get : 根据索引 获取值
		System.out.println(list.get(1));
		// 个数
		System.out.println(list.size());
		// 是否包含(调用equals)
		System.out.println(list.contains(2));
		System.out.println(list);
		// 注意 : remove有方法重载,一个int (要删除的索引)  一个 object(要删除的数据)
		// 这个2 是删除的索引,并不是要删除2这个元素
		list.remove(1);
		// 这样才是删除2这个数据
		list.remove(new Integer(2));
		System.out.println(list);
	}

}

//
11
4
true
[8, 11, 2, 5]
[8, 5]

LinkedList:

  • 队列 : 先到先得 , 栈 : 先进后出

  • 链表 : 链表中保存节点,而一个节点有三部分 1 添加的数据 2 上一个节点 3 下一个节点
    链表是没有下标的,只能从头一个个找,所以查找慢

  • 由于链表中 都是引用指向,所以删除快, 比如 3个元素 分别是 1,2,3 要删除 2 ,

  • 只需要让 1 的下一个 = 1 的下一个的下一个 然后 3 的上一个 = 1的引用

  • LinkedList是模拟的双向链表,就是 1 可以找到 2 , 2 也能找到 1

  • 添加指定位置 / 获取指定位置的值 : 可以传入索引,但是其实不是下标,而是LinkedList封装的方法,帮我们自动循环去找

  • 本质 还是循环,因为链表是非连续的空间,只能从头一个一个找,

  • 只不过LinkedList模拟了下标访问的方式,对我们使用起来,提供了便捷

package Test;

import java.util.LinkedList;
public class Collection_05LinkedList {

	public static void main(String[] args) {
		LinkedList linkedList = new LinkedList();
		// 尾部添加 true
		linkedList.add(1);
		// 尾部添加 void
		linkedList.addLast(2);
		// 插入指定位置
		linkedList.add(0,2);
		// 首部添加 void
		linkedList.addFirst(2);
		// 首部添加 void
		linkedList.push(3);
		// 尾部添加 true
		linkedList.offer(22);
		// 首部添加 true
		linkedList.offerFirst(1);
		// 尾部添加 true
		linkedList.offerLast(4);
		
		// 本质就是在调用两个方法 : linkLast 和 linkFirst
		// 根据下标获取
		System.out.println(linkedList.get(0));
		System.out.println(linkedList.get(0));
		// 获取首元素
		System.out.println(linkedList.getFirst());
		// 获取尾元素
		System.out.println(linkedList.getLast());
		// 删除第一个元素,并返回该元素
		linkedList.pop();
		// 删除最后一个元素,并返回该元素
		linkedList.poll();
		// remove重载  int是根据索引删除, Object 是根据内容删除
		linkedList.remove(1);
		linkedList.remove(  new Integer(22) );
	}

}

//
1
1
1
4

底层实现

  • 节点类
    在这里插入图片描述
  • 添加
    在这里插入图片描述
  • get
    在这里插入图片描述
    在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值