容器集合
Java集合框架包含的内容
Java集合框架提供了一套性能优良、使用方便的接口和类,它们位于java.util包中
Collection是接口,一些Collection允许有重复(唯一)的元素,而另一些不允许(不唯一)。一些Collection是有序的(输入顺序与输出顺序相同),而另一些是无序的
Collection:存储的数据是不唯一、无序的对象
List:存储的数据是不唯一、有序的对象 Set:存储的数据是唯一、无序的对象
唯一:不能重复
有序:输入顺序是否与输出顺序是否一致
Collection:单值集合
集合常见方法:
addAll(): //可以将一个集合中的全部元素,增加到另一个集合之中
clear(): //清除集合中所有元素
contains(): //判断集合中是否包含了指定的对象或元素
containsAll(): //判断集合中是否包含指定集合的所有元素
isEmpty(): //判断集合是否为空
iterator(): //迭代器
removeAll(): //从一个集合中删除另一个集合所包含的所有元素
retainAll(): //两个集合中求交集
List中特有方法
indexOf(): //返回此列表中第一次出现的指定元素索引;如果没有此元素返回-1
lastIndexOf(): //返回此列表中最后出现的指定元素的索引,没有此元素返回-1
set(): //用指定元素替换列表中指定位置的元素
subList(): //截取List集合,左闭右开(按照元素索引来截取)
集合Map的使用
无序
key是唯一的,value是不唯一的
Map:“键值对”集合(key-value),kv一 一对应,可以根据key找到值
Map方法
put(): //加入key和value
get(): //根据key找到value
containsKey(key): //判断是否包含了指定的key
containsValue(value): //判断是否包含了指定的value
//将Map转为单值集合
//转为只包含了Key的单值集合
Set set=map.keySet();
//转为只包含value的单值集合
Collection values =map.values();
//删除
remove(key);根据key删除value
删除:Collection和Map的区别
Collection中的类(List,Set),删除的返回值是boolean
Map中的类,是根据Key删除,返回值是value
如何遍历集合?list set map
1.for循环(普通for循环只适用于有序的集合,建议使用增强for)
2.迭代器(Iterator可用于无序)
//示例
Set set=new HashSet();
set.add("a");
set.add("b");
set.add("c");
/*
hasNext():判断是否存在下一个元素 true|false
如果有下一个元素,则引用后移
next(): 取得当前元素
*/
//迭代器遍历
Iterator iterator = set.iterator();
while ( iterator.hasNext()){
Object next = iterator.next();
System.out.println(next);
}
遍历map:将双值集合,转为单值集合
map-->keySet(取map的key集合)
map-->values(取map的values集合)
可以根据取出的key使用get方法来获取values
关于map的遍历
Map map=new HashMap();
map.put("s01","张三");
map.put("s02","李四");
map.put("s03","王五");
//将双值集合转换为单值集合
Set set = map.keySet();
//增强for循环
for (Object k:set){
System.out.print(k+"-");
//根据key取values
Object o = map.get(k);
System.out.println(o);
}
//通过entry遍历
//取出所有的entry
Set entrys = map.entrySet();
//遍历entry
for (Object e:entrys){
//强转,把e转为entry型
Map.Entry e1 = (Map.Entry) e;
//取key和value
Object key = e1.getKey();
Object value = e1.getValue();
System.out.print(key+"-");
System.out.println(value);
}
//上述代码可以使用泛型:<类型>来进行限制,就不用进行强转
泛型
对于泛型类,Java编译器会将泛型代码转换为普通的非泛型代码,将类型参数T擦除,替换为Object,插入必要的强制类型转换。Java虚拟机实际执行的时候,它是不知道泛型这回事的,它只知道普通的类及代码。再强调一下,Java泛型是通过擦除实现的,类定义中的类型参数会被替换为Object,在程序运行过程中,不知道泛型的实际类型参数
作用:
1.数据安全
2.防止类型转换出错
集合工具类
集合工具类Collections:排序、复制、反转等操作
//查找元素在集合中的索引
//二分查法(使用前,必须保证集合元素是 自然有序的)
Collections.binarySearch(list,val); //list:对象 val:元素
//打乱已有顺序
Collections.shuffle();
//调换两个指定索引位置上的元素 key:索引
Collections.swap(list,key1,key2);
//替换指定元素
Collections.replaceAll(list,oldVal,newVal);
//将集合所有元素替换为指定元素
Collections.fill(list,obj);
比较器
Collections.sort(list)://能够识别有序自然顺序
但是,如果集合中的元素是用户自定义对象,此方法就无法知道应该根据什么排序
根据这种情况Java提供了两个自定义比较器:Comparable和Comparator
Comparable:内部比较器(侵入性,要修改原有代码)
//测试类示例代码
package Exercise.Comparable;
import java.util.ArrayList;
import java.util.Collections;
public class ComparableTest {
public static void main(String[] args) {
ArrayList<Person> list=new ArrayList<>();
//添加元素
list.add(new Person(1,20,"张三",99));
list.add(new Person(2,19,"王五",88));
list.add(new Person(3,25,"赵迁",100));
list.add(new Person(4,25,"李四",100));
//已经实现了Comparable接口,所以可以直接使用sort方法排序
Collections.sort(list);
System.out.println(list);
//在Person类中重写的方法是以年龄来进行升序排序
//可以修改我们需要比较的元素来进行排序
}
}
//Person类代码
package Exercise.Comparable;
public class Person implements Comparable{
private int id;
private int age;
private String name;
private int score;
public Person() {}
public Person(int id, int age, String name, int score) {
this.id = id;
this.age = age;
this.name = name;
this.score = score;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
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;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
@Override
public String toString() {
return
" 学号=" + id +
" 年龄=" + age +
" 姓名='" + name +
" 成绩=" + score+"\n";
}
@Override
//实现了内部比较器,所以需要重写compareTo方法
public int compareTo(Object o) {
//返回1为降序
//返回-1为升序
//返回0为相等
//进行强转
int result;
Person p=(Person) o;
if (this.age>p.age){
result=1;
}else if (this.age==p.age){
/*
如果年龄相同,根据姓名排序,String类型已经重写了Comparable
方法,直接调用即可(默认是升序)
*/
result=this.name.compareTo(p.name);
}else {
result=-1;
}
return result;
}
}
思路:将比较的对象(Person)实现Comparable接口,重写compareTo方法,在compareTo中编写比较的逻辑
重点是返回值代表的顺序
Comparator:外部比较器(无侵入性,不影响原有代码)
1.先定义一个外部比较器
//定义外部比较器代码
package Exercise.Comparator;
import java.util.Comparator;
public class ComparatorWithID implements Comparator {
@Override
public int compare(Object o1, Object o2) {
Student s1=(Student) o1;
Student s2=(Student) o2;
//int型返回相减的数就可以了
return s1.getId()-s2.getId();
}
}
2.在测试类中使用外部比较器
package Exercise.Comparator;
import java.util.ArrayList;
import java.util.Collections;
public class ComparatorTest {
public static void main(String[] args) {
ArrayList<Student> list =new ArrayList<>();
//添加元素
list.add(new Student(12,20,"张三",99));
list.add(new Student(2,19,"王五",88));
list.add(new Student(24,25,"赵迁",100));
list.add(new Student(3,25,"李四",100));
//指定使用外部比较器
Collections.sort(list,new ComparatorWithID());
System.out.println(list);
}
}
//Student类
package Exercise.Comparator;
public class Student {
private int id;
private int age;
private String name;
private int score;
public Student() {
}
public Student(int id, int age, String name, int score) {
this.id = id;
this.age = age;
this.name = name;
this.score = score;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
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;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
@Override
public String toString() {
return
" 学号=" + id +
" 年龄=" + age +
" 姓名=" + name +
" 成绩=" + score+"\n";
}
}
包装类(自动装箱和自动拆箱)
Java语言是面向对象的编程语言,而基本数据类型声明的变量并不是对象,为了弥补这个概念,所以为其提供包装类,增强了Java面向对象的性质。
基本数据类型 | 包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
boolean | Boolean |
char | Character |
float | Float |
double | Double |
装箱:基本数据类型---->包装类(调用包装类的构造器)
Integer i=new Integer(123);
Integer i=new Integer("123");
Boolean b=new Boolean(true);
//注意:在Boolean包装类中,如果转换的不为true,那么无论输入什么,最后转换的一定是false
拆箱:包装类---->基本数据类型(调用包装类Xxx的xxxValue()方法)
Integer i=new Integer(12);
//包装类转换为基本数据类型
int i1=i.intValue();
Float f=new Float(12.1);
//包装类转换为基本数据类型
float=f.floatValue();
JDK 5.0新特性(自动装箱和自动拆箱)
//自动装箱
int num=10;
Integer num2=num;//直接将基本数据类型赋给包装类
//自动拆箱
int num3=num2;//将包装类直接赋给基本数据类型
注意:Integer内部定义了IntegerCache结构,此结构中定义了Integer[],保存了[-128,127]范围内的整数,如果我们使用自动装箱的方式,给Integer赋值的范围在-128到127范围内时,可以直接使用数组中的元素,超过这个范围就需要取new一个对象了
包装类、基本数据类型------>String类型(调用String重载的valueOf(Xxx xxx)方法)
int num=10;
//方式1:连接运算
String str1=num+"";
//方式2:用String的valueOf(Xxx xxx)方法
Srting str2=String.valueof(num);
String类型------>包装类、基本数据类型(调用包装类内的parseXxx()方法)
//示例
String str1="123";
//进行转换
int num=Integer.parseInt(str1);
String str2="true";
//转换布尔
boolean b=Boolean.parseBoolean(str2);