JAVA集合框架
基础概念
集合: 具有相同性质的一类事物,汇成的一个整体
接口框架:
概念: 为了表示和操作集合而规定的一种同一标准的体系结构
内容: 接口,接口的实现类,对集合运算的算法。
- 接口: 表示集合的抽象数据类型。接口中声明了抽象方法,提供了对集合中的内容进行操作的可能性。
- 实现类: 集合框架中接口的具体实现,是可复用的数据结构。
- 算法: 在集合框架接口的实现类对象上完成有用的计算的方法
-
- 如:查找,排序。通常是多态的,被不同类实现时,相同的方法有不同的表现。
注意:
Java中的集合框架所涉及的接口和类,大都是泛型接口和泛型类。
集合框架图
简图1
简图2
知识:
集合的包在java.util下
集合框架的顶层接口:java.util.Collection和Map
迭代器接口:Java.util.Iterator;
编译器技巧
输入数据后,按下 Ctrl+1 ->回车键 会自动补全需要的
例如:
输入:map.values();
按下:Ctrl+1 ->回车键
自动生成:Collection
JAVA.util.Collection接口
常用子接口:
List(序列),Queue(队列),Set(集)
方法:
增删改查
特性:
拥有迭代器:继承迭代器的接口lterable,提供对容器向前遍历的方法
查询是否含有某元素
使用方法:contains()
注意:
如果不是自定义类直接使用即可
如果是自定义类需要:
重写:public boolean equals(Object obj)
,然后再根据题目要求修改
演示代码:
import java.util.*;
class Stu{
String num;
String name;
int age;
char x;
public Stu(String num,String name,int age,char x) {
this.num=num;
this.name=name;
this.age=age;
this.x=x;
}
public String toString() {
return num+" "+name+" "+age+" "+x;
}
//不是 必须要有,但是编译器会自动生成
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
result = prime * result + ((num == null) ? 0 : num.hashCode());
result = prime * result + x;
return result;
}
//必须要有,建议使用编译器自动生成
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Stu other = (Stu) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (num == null) {
if (other.num != null)
return false;
} else if (!num.equals(other.num))
return false;
if (x != other.x)
return false;
return true;
}
}
public class Main {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
ArrayList st=new ArrayList();
int n=sc.nextInt();
for(int i=0;i
对集合排序
使用方法:Collenctions.sort(集合名);
//注意是-tions
注意:
如果不是自定义类:
一般用Tree开头的集合(会自动排序)
如果是自定义的类注意
继承Comparable接口,并重写compareTo方法
演示代码
import java.util.*;
/*********************继承接口********************/
class Stu implements Comparable{
String num;
String name;
int age;
char x;
public Stu(String num,String name,int age,char x) {
this.num=num;
this.name=name;
this.age=age;
this.x=x;
}
public String toString() {
return num+" "+name+" "+age+" "+x;
}
/********************排序规则**************************/
public int compareTo(Stu o) {
// TODO Auto-generated method stub
return this.num.compareTo(o.num);
}
}
public class Main {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
ArrayList st=new ArrayList();
int n=sc.nextInt();
for(int i=0;i
JAVA.util.List接口
定义:
List是元素有序并且可以重复的集合
特点:
- 可以使用下标访问
- 因此可以精准 控制插入某元素的位置/删除某个位置的元素。
实现类:
ArrayList和Vector类
特点:
可以动态改变长度的数组序列
底层是由数组实现的,因此对元素的随机访问速度极快。
缺点:
和数组一样,不适合在线性表中间频繁的插入删除
访问形式:
索引位置,fireach循环,迭代器
Vector类
线程安全的ArrayList类
基本操作
import java.util.Iterator;
import java.util.*;
import java.util.Scanner;
public class Main {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
//List Arrays.List
List list=new ArrayList();
//不指定类型默认为List
小知识:
- 如果在初始化ArrayList的时候没有指定初始化长度的话,默认的长度为10.
2.ArrayList在增加新元素的时候如果超过了原始的容量的话,ArrayList扩容ensureCapacity的方案为“ 原始容量*3/2+1
3.Vector是允许设置默认的增长长度,Vector的默认扩容方式为原来的2倍。
LinkeList类
LinkedList底层是基于双向循环链表的结构实现。
在LinkedList中有一个类似于c语言中结构体的Entry内部类。
在Entry的内部类中包含了前一个元素的地址引用和后一个元素的地址引用类似于c语言中指针
链表的实现,适合频繁的在中间插入删除数据
缺点:
随机访问速度较慢
线程不安全
基本操作:
import java.util.LinkedList;
import java.util.List;
public class LinkedListDemo {
public static void main(String[] args) {
List list = new LinkedList();
list.add("aaa");
list.add("abb");
list.add("abc");
//使用foreach遍历LinkedList
for(String str : list) {
System.out.println(str);
}
//使用数组遍历
String[] strArray = new String[list.size()];
list.toArray(strArray);
for(String str1 : strArray) {
System.out.println(str1);
}
//使用下标访问
System.out.println(list.get(1));
}
}
JAVA.util.Set接口
定义:
Set是元素无序不可重复的的集合
特点:
- 不允许有重复的元素
- 最多允许一个null元素对象。
(虽然Set中元素没有顺序,但是元素在set中的位置是由该元素的HashCode决定的,其具体位置其实是固定的。) - 没有索引
实现类
HashSet类
(最常用)
底层基于Hash算法进行储存相关元素(基于HashMap)
所表示的集合中,元素是无序的并且不允许重复,因此不能利用索引位置访问元素。
注意
- HashSet中允许存放null值(但是在HashSet中仅仅能够存入一个null值)
- HashSet中存储元素的位置是固定的
(虽然Set中元素没有顺序,但是底层是基于Hash算法实现的,元素在set中的位置是由该元素的HashCode决定的,其具体位置其实是固定的。)
基本操作
import java.util.Iterator;
import java.util.*;
import java.util.Scanner;
public class Main {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
//创建
Set set=new HashSet();
//添加
set.add("add");
set.add(123);
set.add(123);
set.add(1.5);
//判断是否含有某元素
System.out.println(set.contains("apple"));
//输出: false
//遍历输出
Iterator it=set.iterator();
while(it.hasNext()) {
Object object=it.next();
}
sc.close();
}
}
LinkedHashSet类
LinkedHashSet具有set集合不重复的特点,以插入(输入)的顺序为迭代顺序。
底层以链表实现
上关系: LinkHashSet不仅是Set接口的子接口而且还是上面HashSet接口的子接口。
TreeSet类
TreeSet是一种排序二叉树。存入Set集合中的值,会按照值的大小进行相关的排序操作。
底层算法是基于红黑树来实现的。(通过TreeMap实现的)
JAVA.util.Map接口
定义:
Map接口实现的是一组Key-Value的键值对的集合。
特点:
- Map中的每个成员方法由一个关键字(key)和一个值(value)构成。
- 键key不能重复,值value不受限制
-
- 若相同键key,多次输出value,系统保留最后一个value
- 每个键只能与一个成员元素相对应。
注意:
- Map接口不直接继承于Collection接口
- Map中的键-值对以Map.Entry类型的对象存在
- 支持泛型Map
访问方法:
键集合,值集合,Entry集合
实现类
HashMap和Hashtable类
HashMap基于Hash数组实现,若Key的Hash值相同则使用链表方式进行保存。
上关系:
HashMap实现了Map、CloneMap、Serializable三个接口,并且继承自AbstractMap类。
注意:
- 新建一个HashMap时,默认的话会初始化一个大小为16,负载因子为0.75的空的HashMap
- 线程不安全,可以在列表中放置一个key为null的元素,也可以多个value为null的元素
Hashtable:
线程安全,不允许键和值有null的元素。
基本操作
import java.util.Iterator;
import java.util.*;
import java.util.Scanner;
public class Main {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
//建立
Map map=new HashMap();
//添加元素
map.put(1, "abc");
map.put(false, 100);
map.put(200, '1');
// 修改元素
map.replace(1, "new");
// 删除元素
map.remove(200);
// 查询元素
String f = (String)map.get(1);//如果定义泛型,则无需强转
System.out.println("F的值为:" + f);
// 输出结果:F的值为:abc
//查询元素2
String f2=(String)map.getOrDefault(12, "0");//如果存在则输出,如果不存在输出0
System.out.println("F的值为:" + f2);
//查询是否有该键值
System.out.println(map.containsKey(1));
//输出结果:true
//遍历:foreach
//遍历:用迭代器
// 遍历key
Set keySet =map.keySet();
Iterator it1=keySet.iterator();
while(it1.hasNext()) {
Object key=it1.next();
Object value=map.get(key);
System.out.println(key+"-"+value);
}
System.out.println("------------------");
//遍历value
Collection values = map.values();
Iterator it2=values.iterator();
while(it2.hasNext()) {
Object value =it2.next();
System.out.println(value);
}
System.out.println("====================");
//遍历entry
Set entrySet=map.entrySet();
Iterator it3=entrySet.iterator();
while(it3.hasNext()) {
Map.Entry entry=(Map.Entry)it3.next();
Object key=entry.getKey();
Object value=entry.getValue();
System.out.println(key+"--"+value);
}
// 遍历map-forEach方法(Java8新特性)
map.forEach((k,v)->
System.out.println("key : " + k + "; value : " + v)
);
sc.close();
}
}
LinkedHashMap
linkedHashMap最大的特点是先进先出的顺序(输入顺序),底层依靠双向链表和Hash表来实现的。
(带有linked,就表示底层用的是链表来进行的存储。)
TreeMap类
TreeMap对 键集合 按顺序存放
因此它便有一些扩展的方法:
firstKey(),lastKey()等,你还可以从TreeMap中指定一个范围以取得其子Map。