一、集合的概念
集合:将若干用途、性质相同或相近的“数据”组合而成的一个整体
Java集合中只能保存引用类型的数据,不能保存基本类型数据
数组的缺点:长度不可变
Java中常用集合:
1.Set(集):集合中的对象不按特定方式排序,并且没有重复对象
2.List(列表):集合中的对象按照索引位置排序,可以有重复对象,允许按索引位置索引对象
3.Map(映射):集合中的每个元素包含一个键对象和值对象,集合中没有重复的键对象,值对象可以重复
二、Collection接口
public class CollectionTest {
public static void main(String[] args) {
//Collection是接口,需要用实现类创建对象
Collection c = new ArrayList();
//集合中保存多少长度
System.out.println("获取集合的长度"+c.size());
//如果没有数据返回true,有数据返回false
System.out.println("判断集合是否为空"+c.isEmpty());
//往集合中添加数据用add方法
c.add("张三");
//集合中是不能保存基本数据类型的,只能保存对象类型
//而基本数据类型可以保存的原因是jdk1.5之后基本数据类型会跟包装类类型进行默认转换
c.add(123);
c.add(true);
c.add('a');
c.add(99.5);
//集合重写了Object的toString方法,所以打印显示的内容不是地址
System.out.println(c);
System.out.println(c.size());
//删除集合中的数组
c.remove(123);
System.out.println(c);
//删除数据之后集合的长度会发生改变,但是数组的长度不会
System.out.println(c.size());
//将集合转换为数组的方法
Object []objects = c.toArray();
for(Object o :objects){
System.out.println(o + " ");
}
}
}
三、Iterator接口
Iterator接口的作用:遍历容器中的元素
Iterator接口的方法:
boolean hasNext()
Object next()
void remove()
public class IteratorTest {
public static void main(String[] args) {
//Collection是接口,需要用实现类创建对象
Collection c = new ArrayList();
c.add(123);
c.add(true);
c.add('a');
c.add(99.5);
//使用迭代器遍历集合
Iterator it = c.iterator();
//hasNext方法用于判断后面是否还有数据,如果有则返回true,如果没有数组则返回false
while(it.hasNext()){
//next方法用于获取集合中的数据
System.out.println(it.next());
}
}
}
四、Set
1.Set接口未提供额外的方法
2.Set的实现类:HashSet、TreeSet
3.HashSet类:按照哈希算法存取集合中的对象
(1)哈希算法判断集合中的元素是否重复,先判断对象的hashcode,然后使用equals()方法
(2)为了使HashSet正常工作,类重写equals()方法时必须重写hashcode()方法,以保证两个引用同一对象的两个变量的hashcode也一致
4.TreeSet:能够对集合中的对象进行自动排序
(1)集合中的对象必须可以比较
(2)自然排序:集合中的对象进行比较,然后进行升序排列
集合中对象的类必须实现java.lang.Comparable接口,使用compareTo()方法进行比较
Java类库中实现Comparable接口的常用类
(3)自定义排序
如果希望TreeSet类的对象按着自定义方式排序,需要让集合中对象的类实现java.util.Comparator接口
5.set集合不可以重复的不仅仅是同一个对象不能保存进set集合,不同对象,内容相同的也不能保存进集合中说到比较首先想到的是equals但是set集合为了提交比较效率会先进行hash比较,hash值是对象的内容经过一系列hash计算,得到的一个整数。如果两个对象的hash值不同,则表示不是同一个对象,如果hash值相同,则证明这两个对象可能是同一个对象,要进行equals比较,方法出现hash值相同,但是内容不同的情况偶然发生。
public class SetTest {
public static void main(String[] args) {
//set集合特点,无序(指添加到集合中的顺序和显示集合的顺序不一致+)不可以重复
Set set = new HashSet();
set.add(123);
set.add(true);
set.add('a');
set.add(99.5);
//set集合无序不可以重复,不仅仅是同一个对象不能重复,不同对象内容重复也不能保存到set集合里
String s1 = "world";
String s2 = new String("world");
set.add(s1);
set.add(s2);
System.out.println(set);
}
}
public class Test {
public static void main(String[] args) {
Set set = new HashSet();
Student s1 = new Student(1001,'l',18);
Student s2 = new Student(1001,'l',18);
Student s3 = new Student(1001,'s',20);
set.add(s1);
set.add(s2);
set.add(s3);
System.out.println(set);
}
}
class Student{
int no;
char name;
int age;
public Student (int no,char name,int age){
this.age = age;
this.name = name;
this.no = no;}
//要想让自己写的类在set集合中正常保存,就需要重写equals的同时重写hashCode方法
//正常保存指的是同一个对象不能保存进集合中,不同对象内容相同也不能保存进集合中
@Override
public boolean equals(Object o) {
if(this == o ){
return true;
}//判断o对象是不是有Student创建的
if(o instanceof Student){
Student s = (Student)o;
//在逐一比较每个属性的值是否相同
if (age == s.age&&name ==s.name&&no==s.no){
return true;
}
}
return false;
}
@Override
public int hashCode() {
return age*5+name*5+no*5;
}
}
五、List
1.List元素都对应一个整数类型的序号记录其在集合中的位置,可以根据序号存取集合中的元素
2.List的实现类:ArrayList、LinkedList等
3.Arrays补充方法:List asList(数组类型 a)
4.ArrayList:
(1)代表长度可变的数组
(2)查询速度较快、增删改速度较慢
5.LinkedList:
(1)采用链表数据结构,对顺序访问进行优化
(2)增删改速度较快,查询速度较慢
注意:一定要实际问题实际分析,规律可能会发生变化
public class ListTest {
public static void main(String[] args) {
//list集合有序可以重复,可以通过索引获取对应位置的数据
List list = new LinkedList();
list.add(123);
list.add("hello");
list.add(false);
list.add(true);
list.add(98.2);
list.add('l');
System.out.println(list);
//get方法,通过索引获取对应位置的数据
System.out.println("获取索引为2,第三个位置的数据"+list.get(2));
//set方法,修改指定位置的数据的值
list.set(1,"hello world");
System.out.println(list);
//在指定索引位置添加数据
list.add(1,"hello");
System.out.println(list);
//删除指定索引位置的数据
list.remove(1);
System.out.println(list);
//将数组转换为集合,那么数组保存数据类型必须是对象类型,基本数据类型要使用包装类
Integer[] a = {1,2,3,4,5,6,7,8,9};
List list1 = Arrays.asList(a);
System.out.println(list1);
//List集合的便利形式
//第一种转换数组在遍历
Object[] object = list1.toArray();
for (Object o: object){
System.out.print(o + " ");
}
System.out.println();
//第二中使用迭代器遍历
Iterator it = list1.iterator();
while (it.hasNext()){
System.out.print(it.next()+" ");
}
System.out.println();
//第三种,直接遍历使用get方法获取数据
for (int i=0;i<list1.size();i++){
System.out.print(list1.get(i)+" ");
}
System.out.println();
//第四种使用foreach循环遍历
for(Object o:list1){
System.out.print(o + " ");
}
}
}
六、Map
1.Map中存储的元素通常都是由key来表示,所以同一Map中key值不能重复,value值无要求
2.Map的实现类:HashMap、TreeMap
3.Map接口的属性:Entry——映射项(键-值对)
public class MapTest {
public static void main(String[] args) {
Map map = new HashMap();
//Map集合以键值对的形式保存数据,键不能重复,值可以重复
//put方法往Map集合中保存数据
map.put("a","123");
map.put(1,false);
map.put('a',95.5);
map.put(true,100);
System.out.println(map);
//map集合保存数据要求key不能重复,但是如果重复了也不会报错
//会用心地value值将之前的数据覆盖掉
map.put(true,200);
System.out.println(map);
//get方法,根据key值获取对应的value值
System.out.println(map.get(true));
//根据key值删除map集合中的数据
map.remove('a');
//当要删除的key不存在的时候,代码书写执行不会报错,就是没有删除而已
map.remove(false);
System.out.println(map);
System.out.println("获取map集合中的元素个数" + map.size());
//clear清空集合
//map.clear()
//遍历map集合
//1.通用遍历形式 最通用
Set set = map.entrySet();
Iterator it = set.iterator();
while (it.hasNext()){
Map.Entry entry = (Map.Entry) it.next();
System.out.println("保存数据时候的key值" + entry.getKey());
System.out.println("保存数据时候的value值" + entry.getValue());
System.out.println();
}
//2.特殊形式的遍历
Map map1 = new HashMap();
//当key值都是有规律的,且不同的是一段连续的数字,那么就可以通过get方法来获取
//数据,从而遍历集合
map1.put("item0","123");
map1.put("item1","true");
map1.put("item2",'k');
map1.put("item3","k");
map1.put("item4",1000);
for (int i = 0;i<map1.size();i++){
System.out.println(map1.get("item"+i));
}
}}
七、Collections类
java.util.Collections类:提供一系列的基于集合操作的常用静态方法
public class CollectionsTest {
//Collection类是专门操作集合的类
public static void main(String[] args) {
List list = new ArrayList();
list.add("hello");
list.add("zhangsan");
list.add("zhao");
list.add("wangwu");
list.add("liuxuiang");
list.add("zhaoliu");
//排序
Collections.sort(list);
System.out.println(list);
//倒序
Collections.reverse(list);
System.out.println(list);
//乱序
Collections.shuffle(list);
System.out.println(list);
}
}
public class Demo {
public static void main(String[] args) {
List list = new ArrayList();
Teacher t1 = new Teacher(1001,"张三",18);
Teacher t2 = new Teacher(1002,"张四",19);
Teacher t3 = new Teacher(1003,"张五",20);
list.add(t1);
list.add(t2);
list.add(t3);
Collections.sort(list);
System.out.println(list);
}
}
class Teacher implements Comparable{
int no;
String name;
int age;
public Teacher (int no,String name,int age){
this.no = no;
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Teacher{" +
"no=" + no +
", name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public int compareTo(Object o) {
if (o instanceof Teacher){
Teacher t = (Teacher) o;
//this 表示的是前一个数, o表示的是数组中的后一个数·
//-1表示不需要交换,正数表示需要交换返回正数就行
if (t.age>this.age){
return -1;
} else if(t.age<this.age){
return 1;
}
}
return 0;
}
}
八、泛型
1.为何使用泛型?
进入集合的对象都当作Object类型,从而失去了自己的类型;取出后也是Object类型,使用前通常要进行强制转换容易出现ClassCastException异常
2.原因:装入集合的时候无法指定装入的元素是何种类型
3.泛型:
(1)装入集合的时候指定元素的具体的类型
(2)增强程序的稳定性与可读性
4.集合中使用泛型
5.定义泛型类
(1)使用<T>用来声明一个型态持有者名称T(可以替换其它标示符)
(2)在定义泛型类时,可以声明多个泛型类型
一般形式:class 类名称 <T1,T2>
(3)声明及配置对象时不一定指定型态,默认会使用Object型态,编译时编译程序会提出警告
(4)可以使用泛型机制来声明一个数组(可以用数组代理T)
(5)不可以使用泛型来建立数组的实例(不能new T[])
6.限制泛型的可用类型
一般形式:class 类名称 <T extends anyClass>
anyClass为类或接口,此类中的泛型必须是实现或继承了anyClass
7.使用类型通配符
一般形式:泛型名称<? extends anyClass>(设定上限)
一般形式:泛型名称<? super anyClass>(设定下限)
public class GenericTest {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("123");
list.add("hello");
//添加泛型之后,在想往集合中和保存其它类型的数据就会报错
//list.add(123)
System.out.println(list);
//泛型不会让保存到集合中的数据丢失自己本身的类型,所以取值的时候就不需要进行类型转换了
Iterator<String> it = list.iterator();
while (it.hasNext()){
String s = it.next();
System.out.println(s);
}
//集合中只能保存对象类型,所以在写泛型的时候只能写包装类型不能写基本数据类型
Map<String,Integer> map = new HashMap();
map.put("a",5);
}
}