集合
集合的概念
- 集合是java对数据结构及算法的封装
- 集合类(需要掌握的有Iterator、Collection、Set、List、HashSet、TreeSet、ArrayList、LinkedList、Map、HashMap、TreeMap )
List
-
List是Collection的子接口。
-
List中常用的抽象方法
- add:添加元素的行为
- addAll:添加一个集合到当前集合中来的行为
- remove:移除元素的行为
- clear:清空元素的行为
- iterator:得到集合迭代器的行为,通过迭代器可以遍历元素
- get:获取指定位置的元素
- size:获取元素个数的行为
-
List的实现类
- ArrayList
- LinkedList
ArrayList的使用
- ArrayList是一个泛型类,泛型约束了ArrayList的数据结构中存储的元素类型。
ArrayList - 创建ArrayList对象:
-ArfaxListString> cities = new ArrayList() - List中所有的抽象方法在ArrayList中都有实现,都可以直接调用
- ArrayList中元素插入的顺序和其存储顺序是一致的
- ArrayList在底层是使用数组往存储数据
//ArrayList的使用
public void m1() {
List<String> list=new ArrayList<String>();
//向集合中添加元素
list.add("abc");
list.add("你好");
list.add("123");
list.add("abc");
System.out.println("集合的大小是:"+list.size());//获取集合的大小
list.remove(2);//根据下标移除一个元素
System.out.println("集合的大小是:"+list.size());
System.out.println(list.get(1));//根据下标获取一个元素
list.clear();//清空集合
System.out.println(list);
}
public void m2(){
List<Integer> list=new LinkedList<Integer>();
list.add(1);
list.add(2);
list.add(3);
System.out.println(list);
list.remove(2);
System.out.println("移除元素后:"+list);
list.clear();
System.out.println("清空元素后:"+list);
}
Vector的使用(了解)
- Vector的使用和ArrayList相同
- Vector在底层也是使用数组来存储数据的
- Vector对数据的操作( add或者get)都是同步方法
- 但是,在现实的开发中,同步操作都是由程序员自己加上去的,一般使用ArrayList,然后自己决定同步的位置就可以了。
//Vector的使用
public void m3(){
List<Students> list=new Vector<Students>();
//添加一个对象到集合中
list.add(new Students(500, "孙悟空"));
list.add(new Students(300, "max"));
System.out.println(list);
}
接口:List实现类:
(1) ArrayListC底层是数组,查询、修改元素时较快)
(2) LinkedList(底层是链表,增加、删除元素时速度较快>
(3) vector(底层也是数组,线程安全的》
1、使用防型指定集合中元擦的类型
2,可以添加任刘类型的蹶据,用Object表示,如果是基本骸据类型,则用时装类表示
3,添加元崇的顺序与集合中存储数据的藏序相同
4,便含中可以存在重复的元素
4,可以添加null值,但是排序时不能使用
List的遍历
ArrayList与LinkedList的异同
相同点
- 方法名相同,处理结果相同(虽然实现不同)
- 存取元素的顺序是一致的(存入0号元素,从0号也会取出相同元素)
- 同一个元素可以多次加入
- ―线程不安全(在操作数据结构时,没有线程保护机制)
区别
- ArrayList使用数组保存元素
- LinkedList使用双向链表保存元素
ArrayList是使用数组保存元素的,因此,在查询、修改元素时有优势,但是在元素增删时效率较低(动态扩容)。
LinkedList是使用双向链表保存元素的,因此,在增删元素时有优势,但是在查询元素时效率低(链表遍历)。
ArrayList与Vector的异同
相同点
- 方法名相同,处理结果相同(虽然实现不同)
- 存取元素的顺序是一致的(存入0号元素,从0号也会取出相同元素)
- 同一个元素可以多次加入
- 底层数据的存储方式相同(都是数组)
区别
- ArrayList对数据的操作没有自带同步,因此是非线程安全的
- Vector对数据的操作自带同步,因此是线程安全的
List的遍历方式有3种:
- 使用for循环遍历使用
- foreach遍历
- 使用iterator遍历
public void m5(){
List<String> list=new ArrayList<String>();
list.add("abc");
list.add("123");
list.add("你好");
list.add("hello");
//for循环遍历
System.out.println("for循环遍历");
for(int i=0;i<list.size();i++){
System.out.print(list.get(i)+"\t");
}
//foreach循环遍历
System.out.println("\nforeach循环遍历");
for (String string : list) {
System.out.print(string+"\t");
}
//使用iterator遍历
System.out.println("\n使用iterator遍历");
Iterator<String> lt=list.iterator();
while(lt.hasNext()){
System.out.print(lt.next()+"\t");
}
}
List的排序(从小到大)
对基本数据类型或String类排序∶
-
Collections.sort(mArrayList)
-
对自定义数据类型排序
-
自定义数据类型需要实现Comparable接口,并实现compareTo方法来自定义排序规则。
-
class Data implements Comparable:泛型类型表示需要被比较的数据类型。
-
compareTo方法返回正数表示当前对象大于比较对象
package cn.iceson;
public class Students implements Comparable<Students>{
private int age;
private String name;
public Students(int age, String name) {
super();
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Students [age=" + age + ", name=" + name + "]";
}
//指定排序规则
@Override
public int compareTo(Students o){
/*//根据age进行排序
int r=this.age-o.age;
if (r>0) {
return 1;//升序排序
}else if(r<0){
return -1;
}else {
return 0;
}*/
//根据name进行排序
int r=this.name.compareTo(o.name);
if (r>0) {
return -1;//降序排序
}else if(r<0){
return 1;
}else {
return 0;
}
}
}
package cn.iceson;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class ListDemo {
//对整型数据(基本类型)排序
public void m1(){
List<Integer> list=new ArrayList<Integer>();
list.add(32);
list.add(23);
list.add(27);
list.add(9);
list.add(15);
list.add(45);
System.out.println("排序前:"+list);
//升序排序
Collections.sort(list);
System.out.println("排序后:"+list);
Collections.reverse(list);
System.out.println("倒置后:"+list);
Collections.shuffle(list);
System.out.println("洗牌后:"+list);
}
//对String类型进行排序
public void m2(){
List<String> list=new ArrayList<String>();
list.add("abc");
list.add("hello");
list.add("good");
list.add("stone");
list.add("date");
list.add("void");
System.out.println("排序前:"+list);
Collections.sort(list);
System.out.println("排序后:"+list);
}
public void m3(){
List<Students> list=new ArrayList<Students>();
list.add(new Students(23, "max"));
list.add(new Students(32, "abc"));
list.add(new Students(22, "mara"));
System.out.println("排序前:"+list);
Collections.sort(list);
System.out.println("排序后:"+list);
}
public static void main(String[] args) {
new ListDemo().m3();
}
}
Set的使用
Set是Collection的子接口。
Set用来存储元素(数据结构),并提供操作元素的方法(算法)。
Set中常用的抽象方法和List中的差不多
- add:添加元素的行为
- remove:移除元素的行为
- clear :清空元素的行为
- iterator:得到集合迭代器的行为,通过迭代器可以遍历元素
- size:获取元素个数的行为
HashSet存储数据的特点
-
元素顺序不可测
-
HashSet底层使用Hash算法决定元素的存储位置。
Hash算法又叫散列算法,其核心思想就是一个萝卜一坑。在一定的区域内,为每一个元素的存储计算出唯一
的地址。如果元素存放太满,重新规划区域,每一个元素的存储地址也会被重新计算。
-
存储元素不可重复
-
元素没有序号,不能通过下标获取元素
//HasSet的使用
public void m1(){
Set<Character> set=new HashSet<Character>();
set.add('a');
set.add('c');
set.add('b');
set.add('t');
set.add('f');
System.out.println(set);
TreeSet可以存储基本类型的数据,也可以存储自定义类型的数据
存储基本类型数据时元素会自动排序
存储自定义类型数据时∶
- 元素必须实现Comparable接口,指定排序规则
- 元素的顺序和排序规则有关
- 插入到TreeSet中的元素自动排序
/**
* 接口:Set
* 实现类:HasSet TreeSet(排序)
* 1.元素的添加次序与存储次序无关
* 2.元素不重复
* 3.TreeSet在添加元素时,会对元素进行排序
*/
public void m2(){
Set<String> set=new TreeSet<String>();
set.add("abc");
set.add("hello");
set.add("world");
set.add("data");
set.add("creat");
set.add("hi");
System.out.println(set);//结果:[abc, creat, data, hello, hi, world]
}
//TreeSet的使用:对自定义类型排序,要求自定义类实现Comparable接口,并重写方法定义排序规则
public void m4(){
Set<Student> set=new TreeSet<Student>();
set.add(new Student(1, "孙悟空", '男'));
set.add(new Student(4, "唐僧", '男'));
set.add(new Student(2, "沙僧", '男'));
set.add(new Student(5, "猪八戒", '男'));
set.add(new Student(3, "白龙马", '男'));
System.out.println(set);
}
Set的遍历
public void m1(){
Set<Character> set=new HashSet<Character>();
set.add('a');
set.add('c');
set.add('b');
set.add('t');
set.add('f');
System.out.println("foreach遍历:");
for (Character character : set) {
System.out.println(character);
}
System.out.println("-----------------------");
System.out.println("Iterator遍历:");
Iterator<Character> iterator=set.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
HashSet和TreeSet的异同
相同点
- 元素不可重复
- 元素没有下标,只能通过迭代器和foreach遍历
- 不支持手动排序(不能修改元素间的位置关系)
- 元素顺序和加入顺序无关
不同点
- HashSet底层使用Hash算法,元素的顺序不可预知,保存的元素没有特殊要求,可以插入null。
- TreeSet底层使用树的算法,元素的顺序和元素的排序规则有关,加入元素必须实现Comparable接口,不能插入null。
Map的使用
Map
-
Map是表示用来存储键值对的接口,Map中的键不可以重复,每一个键最多对应一个值。
-
Map中常用的抽象方法
-
put:存放键值对
-
remove :移除指定键值对
-
clear :清空所有键值对
-
get:获取键对应的值
-
keySet:获取所有键组成的Set
-
-
Map中的元素没有下标,只能通过键获取对应的值
-
Map接口常用的实现类
- HashMap
- TreeMap
HashMap
- HashMap存储数据的特点
- 键值对存储顺序不可测
- HashMap底层使用Hash算法决定键的存储位置。
- 键不可重复
- 只能通过键获取值
public void m1(){
Map<String, Object> map=new HashMap<String,Object>();
//添加键值对
map.put("int", 123);
map.put("String", "abc");
map.put("char", 'f');
map.put("obj", new Student());
System.out.println(map);
map.remove("obj");//按照键移除元素
System.out.println("移除元素后:"+map);
System.out.println(map.get("String"));
map.clear();//清空map中的所有元素
System.out.println("清空map后:"+map);
}
TreeMap
- TreeMap存储数据的特点
- 键必须实现Comparable接口,指定排序规则
- 键的顺序和排序规则有关
- 插入到TreeMap中的元素自动排序
package cn.iceson;
public class Student implements Comparable<Student>{
private int id;
private String name;
private char sex;
public Student(int id, String name, char sex) {
super();
this.id = id;
this.name = name;
this.sex = sex;
}
public Student() {
}
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 char getSex() {
return sex;
}
public void setSex(char sex) {
this.sex = sex;
}
@Override
public String toString() {
return id+":"+name+":"+sex;
}
@Override
public int compareTo(Student o) {
int r=this.name.compareTo(o.name);
if (r>0) {
return 1;//升序排序
}else if (r<0) {
return -1;
}else {
return 0;
}
}
}
//TreeMap的使用:对自定义类型进行排序
public void m3(){
Map<Student,Object> map=new TreeMap<Student,Object>();
map.put(new Student(4,"d",'男'), 12);
map.put(new Student(3,"c",'男'), "abc");
map.put(new Student(1,"a",'男'), true);
map.put(new Student(2,"b",'男'), 'X');
System.out.println(map);
}
Map遍历
集合Map遍历
-
Map的遍历方式有两种︰
- foreach遍历
- Iterator遍历
-
无论使用哪种遍历方式,都需要先得到Key所对应的Set对象,然后使用foreach ,iterator来遍历这个Set对象,并根据遍历的Key获取对应的值。
public void m1(){
Map<String, Object> map=new HashMap<String,Object>();
//添加键值对
map.put("int", 123);
map.put("string", "abc");
map.put("char", 'f');
map.put("obj", true);
System.out.println("foreach遍历:");
Set<String> set=map.keySet();//得到一个Set集合,这个集合中装了所有的键名
for (String key : set) {
System.out.println(key+":"+map.get(key));
}
System.out.println("-------------------------");
System.out.println("Iterator遍历:");
Set<String> set2=map.keySet();//得到一个Set集合,这个集合中装了所有的键名
Iterator<String> it=set2.iterator();//通过iterator得到一个Iterator对象
while(it.hasNext()){//判断是否有下一个键名存在
System.out.println(it.next()+"----"+map.get(it.next()));
}
}
HashMap和TreeMap的异同
-
相同点
- 键不可重复
- 只能通过迭代器和foreach遍历键,然后获取值
- 不支持手动排序(不能修改元素间的位置关系)
- 元素顺序和加入顺序无关
-
不同点
-
HashMap底层使用Hash算法计算键的存储位置,键的顺序不可预知,保存的键没有特殊要求,可以插入null。
-
TreeMap底层使用二叉树存储键,键的顺序和键的排序规则有关,加入的键必须实现Comparable接口,不能插入null。
List ,Set ,Map比较
- List
- 存储的元素可以重复。
- 可以通过下标查询元素。
- 可以手动修改元素的顺序(可以排序,逆序,洗牌等操作)。
- 通过for , foreach , iterator遍历
- Set
- 存储的元素不可以重复
- 不能通过下标访问元素
- 不可以手动修改元素的顺序
- 通过foreach和iterator遍历
- Map
- 保存键值对信息-键不可以重复
- 不可以手动修改顺序
- 通过foreach和iterator遍历