Java-集合框架

本文详细介绍了Java集合框架的基础知识,包括集合、数组与集合的区别、集合框架的构成与分类,以及List、Set等常见集合的特性与使用方法。重点讲解了List集合的特性与特有方法、迭代器的使用,HashSet如何保证元素唯一性,TreeSet如何实现排序。

集合框架

第一部分

1、数据、对象和集合

面向对象操作的是对象,数据多了需要进行封装,封装成了对象,对象多了也需要存储,对象多了用集合存储;

2、数组和集合的区别

数组:长度是固定的,存的对象只能是同一个类型的;
集合:可变长度,只要是对象都可以存储;

3、集合框架

|--集合框架的构成以分类
Collection
|--List
|--ArrayList
|--LinkedList
|--Vector

|--Set

|--HashSet

|--TreeSet

|--容器之间的区别

这些容器对数据的存储方式不同,这种存储方式称之为:数据结构;

|--集合框架的共性方法

|--add方法的参数类型是Object,以便接收任意类型的对象;

|--集合中存储的都是对象的引用;

|--Collection 接口 //里面的共性方法,基本的操作

boolean add(E e) 添加元素

void clear()  清空集合

boolean remove(Object o) 删除元素

int size()  获取个数,集合长度

boolean contains(Object o)  判断元素是否包含

boolean isEmpty()  判断集合是否为空

boolean retainAll(Collection<?> c) 取两个集合的交集

4、迭代器

概念:就是集合的取出元素的方式;

特点:每个容器里面都有存和取的方式,因为每个容器的数据结构不同,所以它们存取的动作不一样,具体的实现方式也是不同的;就是把取出方式定义在集合的内部,这样取出方式就可以直接访问集合内容的元素,那么取出方式就被定义成了内部类,而每一个容器的数据结构不同,所以取出的动作细节也是不一样的,但是都有共性内容,这个共性内容就是判断和取出,那么可以将这些共性抽取出来,就是Iterator接口;那么这些内部类都符合一个规则,该规则就是Iterator,如何获取集合的取出对象?通过一个对外提供的方法就是iterator();-->取出方式;

Iterator接口
|-- Iterator<E> iterator()  
|--boolean hasNext() 如果仍有元素可以迭代,则返回 true。
|--E next() 获取下一个元素
|--Iterator it  = al.iterator();获取迭代器,用于取出集合中的元素
|--接口型引用只能指向自己的子类对象,而这个对象不是new出来的,而是通过collection集合里面的方法获取到的;

5、List集合

特点:元素是有序的,元素是可以重复的;因为该集合体系有索引;只有List集合里面的元素具备增删改查
List集合特有方法:凡是带有角标操作的都是List集合的特有方法;
|--ListIterator<E> listIterator() List 集合特有的迭代器
|--E set(int index, E element)  只有 List 集合具备:可以改变角标位置上的元素
|--List<E> subList(int fromIndex, int toIndex) 包含头不包含尾
|--int indexOf(Object o) 通过indexOf获取对象的位置
|--int lastIndexOf(Object o) 

6、ListIterator

|--ListIterator:列表迭代器-->ListIterator继承了Iterator ,列表迭代器里面的方法比迭代器里面的方法要多;
|--List集合特有的迭代器,ListIterator是Iterator 的子接口,在迭代时不可以通过集合对象的方法操作集合中的元素,因为会发生ConcurrentModificationException异常,所以,在迭代时,只能用迭代器的方法操作元素。可是Iterator 方法是有限的,只能对元素进行判断,取出和删除操作,如果想要其他的操作如添加,修改等,就需要使用其子接口,ListIterator,该接口只能通过List集合的ListIterator方法获取;
|--需求:想要对集合中的元素取出,在取出的过程中,想做一些操作,如在迭代过程中想要添加或者是删除元素;
问题:如果这时使用的是Iterator迭代器的话,那么会引发并发修改异常:ConcurrentModificationException,意思是说:不能做的是对一组元素,进行多种操作,不能即用集合,又用迭代器操作同一组元素,这样有可能会引发并发修改异常;你在取出元素,我早向里面添加元素,那么你到底要不要取元素?不清楚。
解决:要么就都使用集合的方法,要么就都使用迭代器的方法

7、ListIterator代码体现

import java.util.*;
class ListDemo 
{
	public static void main(String[] args) 
	{
		ArrayList al = new ArrayList();
		al.add("java1");
		al.add("java2");
		al.add("java3");
		al.add("java4");
		sop(al);

		ListIterator li = al.listIterator();
		while(li.hasNext())
		{
			Object obj = li.next();
//			在迭代的过程中,判断元素,并操作元素
			if(obj.equals("java2"))
//				li.add("java009");//在遍历的过程中添加了新的元素
				li.set("java007");//在遍历的过程中修改元素
		}
		sop(al);
/*
		ListIterator li = al.listIterator();//因为add是ListIterator里面特有的方法。所以不好用父类Iterator
		while(li.hasNext())
		{
			Object obj = li.next();
			if(obj.equals("java2"))
				li.add("java009");
		}
		
		sop(al);
		Iterator it = al.iterator();
		while(it.hasNext())
		{
			Object obj = it.next();
			if(obj.equals("java2"))
//				al.add("java008");//不能用集合的方法了。只能用迭代器的方法。
				it.remove();
			sop("obj="+obj);
		}
		sop(al);
		*/
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}
 

8、运行结果

9、Llst集合集体对象特点

Collection
|--List:元素是有序的,元素可以重复,因为该集合体系是有索引的;
|--ArrayList:底层的数据结构使用的是数组结构,特点:查询速度块,但是增删稍慢;线程不同步的;
|--LinkedList:底层使用的是链表数据结构,特点速度很快,查询稍慢;
|--Verctor:底层是数组数据结构,元老级的,同步的,什么都慢;

ArrayList默认的长度是10,当超过了长度10以后,那么就要new一个新的数组,长度为50%的延长,就是15了,然后把原来的元素copy到新的数组里面来

Verctor:默认的长度是10,它是100%的延长,就是变成了20;

相比之下,ArrayList比较好一点;比较节约空间;

10、Verctor

|--枚举就是Verctor特有的取出方式,发现枚举和迭代器很像,其实枚举和迭代是一样的,
|--ArrayList和Verctor的区别:Verctor支持枚举,而ArrayList没有;

11、LinkedList

链表列表实现
LinkedList的特有方法:
|--void addFirst(E e) 
|--addFirst  添加在头部
----
java04
java03
java02
java01
----
|--void addLast(E e) 
|--addLast  添加在尾部
----
java01
java02
java03
java04
----
get方法是获取元素,但不删除元素
|--E getFirst() 
|--E getLast() 
remove方法是获取元素,但是元素被删除
|--E removeFirst()  :是从java01开始remove
|--E removeLast():是从java04开始remove
----
java04
java03
java02
java01
----

12、LinkedList模拟队列和堆栈数据结构

代码体现
<span style="font-family:SimSun;font-size:14px;">/*
使用LinkedList摸以一个堆栈或者队列数据结构;

堆栈:先进后出 如同一个杯子;
队列:先进先出 如同一个水管;

面试的要求是:得把LinkedList给封装到我描述的堆栈或者队列类当中,
隐藏起来,对外暴露更简单的操作
*/
import java.util.*;
class DuiLie
{
	private LinkedList link;
//	一初始化就有了一个link,单独封装一下
	DuiLie()
	{
		link = new LinkedList();
	}
//	添加元素,封装起来,自己能够识别的方法
	public void myAdd(Object obj)
	{
		link.addFirst(obj);
	}
//	取出元素,封装起来,自己能够识别的方法
	public Object myGet()
	{
//		return link.removeFirst();//这个是堆栈,先进后出
		return link.removeLast();//这个顺序是队列,先进先出
	}
//	判断是否是null,封装起来了
	public boolean isNull()
	{
		return link.isEmpty();
	}
}
class LinkedListTest 
{
	public static void main(String[] args) 
	{
//		我自己的容器,只是我的容器基于链表容器;
		DuiLie dl = new DuiLie();
		dl.myAdd("java01");
		dl.myAdd("java02");
		dl.myAdd("java03");
		dl.myAdd("java04");
		while(!dl.isNull())
		{
			sop(dl.myGet());
		}
	}
	public static void sop(Object obj)
	{
		
			System.out.println(obj);
	}

}</span>
 

13、ArrayList练习1

取出重复元素
/*
去除ArrayList集合中的重复元素
定义一个功能,把重复元素去除,
定义一个容器,判断这个新的容器里面有没有元素1,没有的话就存进去,
新容器里面有没有1,有的话就不要,依次判断有没有2,走完以后,新的容器里面的元素就是唯一的;
*/
import java.util.*;
class ArrayListTest 
{
	public static void sop(Object obj)
	{
			System.out.println(obj);
	}
//  返回值类型是ArrayList
	public static ArrayList singleElement(ArrayList al)
	{
		//定义一个临时容器
		ArrayList newAl = new ArrayList();
		Iterator it = al.iterator();
//		我选择,我喜欢
		while(it.hasNext())
		{
			Object obj = it.next();
			if(!newAl.contains(obj))//是否包含用的是contains,不是equals
//				不包含就往里面存;
				newAl.add(obj);
		}
		return newAl;
	}
	public static void main(String[] args) 
	{
		ArrayList al = new ArrayList();
		al.add("java01");
		al.add("java02");
		al.add("java03");
		al.add("java02");
		al.add("java04");
		al.add("java03");
		al.add("java02");
//		打印原集合
		sop(al);
		al = singleElement(al);
//		打印新的集合
		sop(al);
	}
}
 

14、ArrayList练习2

/*
将自定义对象作为元素存到ArrayList集合中,并去除重复元素,
比如:存人对象,同姓名同年龄,视为同一个人,为相同元素;

思路:
1、对人进行描述,将数据封装进人对象;
2、定义容器,将人存入;
3、取出

这边的判断元素是否相同用的是contains方法,包含,而contains的底层原理就是equals;

List集合判断元素是否相同,依据的是元素的equals方法;
*/
import java.util.*;
//而这个Person里面也是有equals方法的,因为Person本身继承Object,但是这个equals方法比较的是地址值;
//而我的这个6个地址值都是不相同的
class Person
{
	private String name;
	private int age;
	
	//下面的两个equals是不同的,一个是覆盖的Object里面的equals方法,一个是字符串姓名内容的比较。
//	需要重新equals,判断的是姓名和年龄
	public boolean equals(Object obj)//这个equals是Person类里面的方法
	{
//		判断是不是Person类,而不是Demo
		if(!(obj instanceof Person))
			return false;
//		强转
		Person p = (Person)obj;
		System.out.println(this.name+"......"+p.name);
		return this.name.equals(p.name) && this.age==p.age;//这个equals是判断字符串是否相同的方法
	}
	/**/
	Person(String name,int age)
	{
		this.name = name;
		this.age = age;
	}
//	获取
	public String getName()
	{
		return name;
	}
	public int getAge()
	{
		return age;
	}
}
class ArrayListTest2 
{
	public static void main(String[] args) 
	{
//		ArrayList判断的是对象是否相同,用的是equals,而所有的对象都是相同的
//		ArrayList里面判断元素是否相同用的是equals方法;
//		返回来的是true就是相同,返回为false就是不相同
		ArrayList al = new ArrayList();
		al.add(new Person("zhangsan01",30));//Object obj = new Person("zhangsan",30)  多态
		al.add(new Person("zhangsan02",33));
		al.add(new Person("zhangsan02",33));
		al.add(new Person("zhangsan03",35));
		al.add(new Person("zhangsan05",37));
		al.add(new Person("zhangsan05",37));

		al = singleElement(al);
//		想要删除一个元素,那么就要拿着这个元素到集合里面去找,怎么去找就是用的equals;
//		sop("remove 03:"+al.remove(new Person("zhangsan05",37)));
		Iterator it = al.iterator();
		while(it.hasNext())
		{
//			Object obj = it.next();//it.next()返回来的是obj
//			Person p = (Person)obj;//想要访问子类的特有的方法的时候需要向下转型。
			Person p = (Person)it.next();//想要访问子类的特有的方法的时候需要向下转型。
			sop(p.getName()+"..."+p.getAge());
		}
	}
//	这个是去除重复的方法;
	public static ArrayList singleElement(ArrayList al)
	{
		ArrayList newAl = new ArrayList();
		Iterator it = al.iterator();
		while(it.hasNext())
		{
			Object obj = it.next();
			if(!newAl.contains(obj))//是否包含用的是contains;调用一次contains,contains就调用一次equals
				newAl.add(obj);
		}
		return newAl;
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}
 

15、运行的结果

第二部分

1、Set集合

|--特点:Set集合:元素是无序的(存入和取出的顺序不一定一致),元素不可以重复;(有序:如何存进去的,就如何取出来)
|--发现Set集合的方法和Collection集合是一致的;
|--Set
|--HashSet:底层数据结构是哈希表;哈希表是按照哈希值来存的;
|--HashSet是如何保证元素唯一性的呢?
是通过元素的两个方法,hashCode和equals来完成,如果元素的hashCode值相同,才会判断equals是否为true
如果元素的hashCode值不同,不会调用equals;

2、哈希值

import java.util.*;
class HashSetDemo 
{
	public static void main(String[] args) 
	{
		Demo d1 = new Demo();
		Demo d2 = new Demo();
		sop(d1);
		sop(d2);

	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}
class Demo
{
}
 

3、哈希值

|--在哈希表里面,当哈希值重复的时候,还有一次校验方式,就是我们的元素的对象是不是相同的;判断是否是同一个对象用的是equals方法;
|--如果判断到的哈希值的地址值是一样的,那么就判断是否是同一个对象,如果不是,那么就在该地址值下顺延;都在同一个地址值上;

|--哈希表结构的特点:先看哈希值,如果哈希值是一样的,在比较砸门是不是同一个对象,用equals比较;

4、HashSet练习

<p><span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px;">/*</span></p><p>往hashSet集合中存入自定义对象
姓名和年龄视为同一个人,重复元素;</p>
定义一个对象通常要复写hashCode和equals,因为有可能你的对象要存到HashSet集合中;
*/
import java.util.*;
class  HashSetTest
{
	public static void main(String[] args) 
	{
		HashSet hs = new HashSet();
//		下面这些元素都有自己的哈希值,
		hs.add(new Person("a4",14));
		hs.add(new Person("a1",11));
		hs.add(new Person("a2",12));
		hs.add(new Person("a2",12));
		hs.add(new Person("a3",13));
		hs.add(new Person("a4",14));
		hs.add(new Person("a4",14));
		hs.add(new Person("a5",15));

//		sop("contains::"+hs.contains(new Person("a1",11)));//判断某个元素是否存在
//		hs.remove(new Person("a2",12));//删除某个元素
		Iterator it = hs.iterator();

		while(it.hasNext())
		{
			Object obj = it.next();
			Person p = (Person)obj;
			sop(p.getName()+"::"+p.getAge());
		}
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}
//描述人
class Person
{
	private String name;
	private int age;
//	覆盖Person的默认的hashCode方法,建立Person自己的hashCode方法;
	public int hashCode()//对象底层自己调用的;
	{
//		按照姓名和年龄来生成一个哈希值;
//		按照条件生成哈希值
//		字符串本身已经实现了hashCode,( String int hashCode()  )
		return name.hashCode()+age*26;
	}
	Person(String name,int age)
	{
		this.name = name;
		this.age = age;
	}
	public String getName()
	{
		return name;
	}
	public int getAge()
	{
		return age;
	}
	//对象底层自己调用的;
	public boolean equals(Object obj)//这个必须要做转换,而且要进行判断是不是这种类型
	{
		if(!(obj instanceof Person))
			return false;
		Person p = (Person)obj;
		System.out.println(this.name+"......"+p.name);//如果这句话打印了,代表equals被调用了;
		return this.name.equals(p.name) && this.age==p.age;
	}

}

5、运行结果

第三部分

1、TreeSet

特点:TreeSet可以对Set集合中的元素进行排序;
|--TreeSet集合:
|--可以对Set集合中的元素进行排序,
|--底层数据结构是二叉树;
|--保证元素唯一性的依据:compareTo方法的return 0;
|--TreeSet集合排序第一种方式:让元素自身具备比较性,元素需要实现Comparable接口,覆盖一个compareTo,还要判断主要条件和次要条件;
这种方式也称为元素的自然顺序,或者叫做默认顺序;
|--TreeSet集合排序第二种方式:当元素自身不具备比较性,或者具备的比较性不是所需要的,这时就需要集合自身具备比较性;
在集合一初始化时,就有了比较性;
当两种排序都存在时,以比较器为主,定义一个类,实现Comparator接口,覆盖compare方法;

2、TreeSet第一种排序方式练习

/*
往TreeSet集合中存储自定义对象学生
想按照学生的年龄进行排序;
*/
import java.util.*;

class TreeSetDemo 
{
	public static void main(String[] args) 
	{
		TreeSet ts = new TreeSet();

		ts.add(new Student("lisi005",24));
		ts.add(new Student("lisi008",20));
		ts.add(new Student("lisi007",22));
		ts.add(new Student("lisi007",22));
		ts.add(new Student("lisi004",22));
//		ts.add(new Student("lisi54",26));
		Iterator it = ts.iterator();
		while(it.hasNext())
		{
//			Object obj = it.next();
//			Student stu = (Student)obj;
			Student stu = (Student)it.next();
			sop(stu.getName()+"::"+stu.getAge());
		}
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}
//Comparable该接口强制让学生具备比较性
class Student implements Comparable
{
	private String name;
	private int age;
//	返回的是一个int型的数据;需要传一个对象进来;
	public int compareTo(Object obj)
	{
//		return 1;//怎么存进去的,就怎么取出来。
//		return -1;//反着取出元素
//		return 0;//元素都是相同的
		
		/*  按照年龄和姓名进行排序。*/

		if(!(obj instanceof Student))
			throw new RuntimeException("此对象不是学生");//抛出的是RuntimeException异常,不是Exception异常
		Student s =(Student)obj;//如果是学生的话,就强转

		System.out.println(this.name+"..compareto.."+s.name);
		if(this.age<s.age)
			return 1;
//		当主要条件相同,就要判断次要条件;
//		当年龄相等时,就要比较姓名
//		int compareTo(String anotherString)  
		if(this.age==s.age)
			return this.name.compareTo(s.name);
		return -1;
	}
	Student(String name,int age)
	{
		this.name = name;
		this.age = age;
	}
	public String getName()
	{
		return name;
	}
	public int getAge()
	{
		return age;
	}
}
 

3、运行结果

4、TreeSet第二种排序方式练习

/*
练习:按照字符串长度排序
字符串本身具备比较性,但是它的比较方式不是所需要的
这时就只能使用比较器 
*/
import java.util.*;
class TreeSetTest 
{
	public static void main(String[] args) 
	{
		TreeSet ts = new TreeSet(new StrLenCompartor());

		ts.add("thwht");
		ts.add("aef");
		ts.add("aaa");
		ts.add("jy");
		ts.add("shda");
		ts.add("yjet");
		Iterator it = ts.iterator();
		while(it.hasNext())
		{
			sop(it.next());
		}
	}
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
}
//类实现Comparator接口
class StrLenCompartor implements Comparator
{
	public int compare(Object o1,Object o2)
	{
//		强转
		String s1 =(String)o1;
		String s2 =(String)o2;
		
		int num = new Integer(s1.length()).compareTo(new Integer(s2.length()));
//		判断次要条件
		if(num==0)
			return s1.compareTo(s2);
		return num;
		/**/
		/*
		if(s1.length()>s2.length())
			return 1;
		else if(s1.length()==s2.length())//主要条件判断如果相同,再判断次要条件,
			return s1.compareTo(s2);//次要条件的判断是通过字符串的compareTo方法。
		return -1;
		*/
	}
}

5、运行结果

第四部分

我的总结

|--LinkedList集合里面有addFirst ,addLast方法,可以总结为addFirst 开始为尾部,addLast开始为头部;
|--removeFirst:是从java01开始remove;
|--removeLast:是从java04开始remove;
|--List集合判断元素是否相同,依据的是元素的equals方法;
|--在ArrayList或者LinkedList的remove和contains底层用的是equals方法;
|--HashSet集合对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashCode和equals方法;
|--哈希表结构的特点:先看哈希值,如果哈希值是一样的,在比较砸门是不是同一个对象,用equals比较;
|--TreeSet集合:排序时,当主要条件相同时,一定要判断一下次要条件;
|--TreeSet集合:想要判断元素是否包含,或者删除元素,走的都是compareTo方法,走的是return 0;
|--TreeSet集合:两种排序:一个是让元素自身具备比较性,一个是让容器自身具备比较性,如果都具备了,以比较器为主;
采用PyQt5框架与Python编程语言构建图书信息管理平台 本项目基于Python编程环境,结合PyQt5图形界面开发库,设计实现了一套完整的图书信息管理解决方案。该系统主要面向图书馆、书店等机构的日常运营需求,通过模块化设计实现了图书信息的标准化管理流程。 系统架构采用典型的三层设计模式,包含数据存储层、业务逻辑层用户界面层。数据持久化方案支持SQLite轻量级数据库与MySQL企业级数据库的双重配置选项,通过统一的数据库操作接口实现数据存取隔离。在数据建模方面,设计了包含图书基本信息、读者档案、借阅记录等核心数据实体,各实体间通过主外键约束建立关联关系。 核心功能模块包含六大子系统: 1. 图书编目管理:支持国际标准书号、中国图书馆分类法等专业元数据的规范化著录,提供批量导入与单条录入两种数据采集方式 2. 库存动态监控:实时追踪在架数量、借出状态、预约队列等流通指标,设置库存预警阈值自动提醒补货 3. 读者服务管理:建立完整的读者信用评价体系,记录借阅历史与违规行为,实施差异化借阅权限管理 4. 流通业务处理:涵盖借书登记、归还处理、续借申请、逾期计算等标准业务流程,支持射频识别技术设备集成 5. 统计报表生成:按日/月/年周期自动生成流通统计、热门图书排行、读者活跃度等多维度分析图表 6. 系统维护配置:提供用户权限分级管理、数据备份恢复、操作日志审计等管理功能 在技术实现层面,界面设计遵循Material Design设计规范,采用QSS样式表实现视觉定制化。通过信号槽机制实现前后端数据双向绑定,运用多线程处理技术保障界面响应流畅度。数据验证机制包含前端格式校验与后端业务规则双重保障,关键操作均设有二次确认流程。 该系统适用于中小型图书管理场景,通过可扩展的插件架构支持功能模块的灵活组合。开发过程中特别注重代码的可维护性,采用面向对象编程范式实现高内聚低耦合的组件设计,为后续功能迭代奠定技术基础。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值