目录
1.集合:
集合和数组一样,可以保存一组数据,并且提供操作集合元素的相关方法,使用更加方便
java集合框架中的相关接口:
java.util.Collection接口:是所有集合的顶级接口,封装了所有集合所共有的方法,下面有多种实现类,因此我们可以有更多的数据结构来选择。
Collection接口下面有两种常见的子接口:
java.util.List:线性表,是可以重复集合,并且有序
java.util.Set:不可重复集合,大部分实现类是无序的
Collection接口的常用方法:
add():向集合中添加一个元素,成功添加则返回true
size():返回当前集合的元素个数
isEmpty():判断当前集合是否是空集,仅当size()为0时返回true
clear():清空集合
contains():判断集合是否包含给定集合
remove():从集合中删除给定元素,成功删除则返回true
package apiday03;
import java.util.ArrayList;
import java.util.Collection;
/**
* Collection集合的演示
*/
public class CollectionDemo {
public static void main(String[] args) {
Collection c = new ArrayList();
c.add(new Point(1,2));
c.add(new Point(3,4));
c.add(new Point(5,6));
c.add(new Point(7,8));
c.add(new Point(9,0));
c.add(new Point(1,2));
//[元素1.toString(), 元素2.toString(), 元素3.toString(), ......]
System.out.println(c); //[(1,2), (3,4), (5,6), (7,8), (9,0), (1,2)]
Point p = new Point(1,2);
/*
boolean contains(Object o)
判断当前集合是否包含给定元素(o)
判断依据是给定元素是否与集合元素存在equals比较为true的情况
*/
boolean contains = c.contains(p);
System.out.println("是否包含:"+contains); //true
/*
boolean remove(Object o) ----一般都是直接调用
从当前集合中删除与给定元素equals比较为true的元素
若存在重复则只删除一次
*/
c.remove(p); //认为能删除的发花,认为不能删除的发火箭
System.out.println(c); //[(3,4), (5,6), (7,8), (9,0), (1,2)]
//集合中存放的是元素的引用
Collection cc = new ArrayList();
Point pp = new Point(1,2);
cc.add(pp); //将pp添加到集合cc中---装的是pp的引用(地址)
System.out.println("pp:"+pp); //(1,2)
System.out.println("cc:"+cc); //[(1,2)]
pp.setX(100);
System.out.println("pp:"+pp); //(100,2)
System.out.println("cc:"+cc); //[(100,2)]
/*
Collection c = new ArrayList();
c.add("one");
c.add("two");
c.add("three");
c.add("four");
c.add("five");
//集合重写了Object的toString()方法,返回格式如下:
//[元素1.toString(), 元素2.toString(), 元素3.toString(), ......]
System.out.println(c); //[one, two, three, four, five]
System.out.println("size:"+c.size()); //5,输出集合的元素个数
//isEmpty()判断集合是否是空集(size()为0表示空集)
System.out.println("是否是空集:"+c.isEmpty()); //false
c.clear(); //清空集合
System.out.println("集合已清空");
System.out.println(c); //[]
System.out.println("size:"+c.size()); //0
System.out.println("是否为空集:"+c.isEmpty()); //true
*/
}
}
addAll():将参数集合中的元素添加到当前集合中,添加后当前集合发生改变则返回true
containsAll():判断当前集合中的所有元素
retainAll():取交集
removeAll():删交集
iterator():获取迭代器
package apiday03;
import java.util.ArrayList;
import java.util.Collection;
/**
* 集合间操作的练习
*/
public class CollectionOperDemo {
public static void main(String[] args) {
Collection c1 = new ArrayList();
c1.add("java");
c1.add("c++");
c1.add(".net");
System.out.println("c1:"+c1); //c1:[java, c++, .net]
Collection c2 = new ArrayList();
c2.add("android");
c2.add("ios");
c2.add("java");
System.out.println("c2:"+c2); //c2:[android, ios, java]
c1.addAll(c2); //将c2添加到c1中
System.out.println("c1:"+c1); //c1:[java, c++, .net, android, ios, java]
System.out.println("c2:"+c2); //c2:[android, ios, java]
Collection c3 = new ArrayList();
c3.add("c++");
c3.add("android");
c3.add("php");
System.out.println("c3:"+c3); //c3:[c++, android, php]
boolean contains = c1.containsAll(c3); //判断c1中是否包含c3中的所有元素
System.out.println("包含所有:"+contains); //false
/*
//取交集,c1中仅保留c1与c3的共有元素,c3不变
c1.retainAll(c3);
System.out.println("c1:"+c1); //c1:[c++, android]
System.out.println("c3:"+c3); //c3:[c++, android, php]
*/
//删交集,将c1中与c3共有的元素删除,c3不变
c1.removeAll(c3);
System.out.println("c1:"+c1); //c1:[java, .net, ios, java]
System.out.println("c3:"+c3); //c3:[c++, android, php]
}
}
2.集合的遍历:
Collection接口提供了统一的遍历集合的方式:迭代器模式。通过iterator()方法可以获取一个用于遍历当前集合元素的迭代器(Iterator接口)
java.util.Iterator接口:定义了迭代器遍历集合的相关操作,不同的集合都实现了用于遍历自身元素的迭代器实现类,但是我们元素记住它们的名字,从多态的角度把它们看成Iterator即可
迭代器遍历遵循的步骤:问(hasNext())、取(next())、删(remove()),其中删除并不是必要操作
package apiday03;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* 迭代器Iterator遍历集合的演示
*/
public class IteratorDemo {
public static void main(String[] args) {
Collection c = new ArrayList();
c.add("one");
c.add("#");
c.add("two");
c.add("#");
c.add("three");
c.add("#");
c.add("four");
c.add("#");
c.add("five");
System.out.println(c); //[one, #, two, #, three, #, four, #, five]
/*
迭代器的常用方法:
1)boolean hasNext()------------问
询问集合是否还有"下一个"元素可供迭代
注意:迭代器默认开始位置在集合第1个元素之前
无论调用多少次hasNext()方法,迭代器的位置都不会改变
2)Object next()----------------取
迭代器向后移动一个位置来指向集合的下一个元素并将其获取
*/
Iterator it = c.iterator(); //获取集合c的迭代器
while(it.hasNext()){ //若有下一个元素
String str = (String)it.next(); //获取下一个元素
System.out.println(str);
if("#".equals(str)){ //若str为#号
//c.remove(str); //迭代器遍历过程中不能通过集合的方法增删元素
it.remove(); //删除next()方法所获取的元素
}
}
System.out.println(c);
}
}
增加for循环/新循环:
JDK1.5时推出了一个特性:增强型for循环,也称为新循环,让我们使用相同的语法来遍历集合和数组
for(元素类型 变量名 : 集合或数组){
循环体
}
3.泛型:
泛型也称为参数化类型,允许我们在使用一个类时,传入某个类型来规定其内部的属性、方法参数或返回值类型,使得我们使用时更加方便
泛型在集合中被泛型使用,用来规定集合元素的类型
若不指定泛型的具体类型,则默认为Object
若指定了泛型的具体类型,则在获取泛型的值时,编译器会做强转操作
package apiday03;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* 泛型的演示
*/
public class GenericDemo {
public static void main(String[] args) {
Collection<Point> c = new ArrayList<>();
c.add(new Point(1,2));
c.add(new Point(3,4));
c.add(new Point(5,6));
c.add(new Point(7,8));
c.add(new Point(9,0));
//c.add("one"); //编译错误,参数类型与集合的泛型类型不匹配
Iterator<Point> it = c.iterator();
while(it.hasNext()){
Point p = it.next(); //编译器会自动补齐强转代码
System.out.println(p);
}
for(Point p : c){
System.out.println(p);
}
/*
Collection<String> c = new ArrayList<>(); //泛型集合
c.add("one");
c.add("two");
c.add("three");
c.add("four");
c.add("five");
//c.add(new Point(1,2)); //编译错误,Point类型违背了集合c所指定的泛型的实际类型String
//迭代器所指定的泛型类型应当与其遍历的集合的泛型一致
Iterator<String> it = c.iterator();
while(it.hasNext()){
String str = it.next(); //编译器会自动补齐强转操作
System.out.println(str);
}
for(String str : c){ //编译器会自动补齐强转操作
System.out.println(str);
}
*/
}
}
4.List集
java.util.List接口,继承自Collection
List集合是可重复集,并且有序,提供了一套可以通过下标操作元素的方法
常用实现类:
java.util.ArrayList:内部使用数组实现,查询性能更好
java.util.LinkedList:内部使用链表实现,首尾增删元素性能更好
List集合常见方法
List集合的特点:可以存放重复元素,并且有序
get()和set()方法
E get(int index):获取指定下标index处对应的元素
E set(int index,E e):将给定元素设置到index指定的位置,返回值为该位置被替换的元素
public class ListDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
// List<String> list = new LinkedList<>();
list.add("one");
list.add("two");
list.add("three");
list.add("four");
list.add("five");
/*
E get(int index)
获取指定下标对应的元素
*/
//获取第三个元素
String e = list.get(2);
System.out.println(e);
for(int i=0;i<list.size();i++){
e = list.get(i);
System.out.println(e);
}
/*
E set(int index,E e)
将给定元素设置到指定位置,返回值为该位置原有的元素。
替换元素操作
*/
//[one,six,three,four,five]
String old = list.set(1,"six");
System.out.println(list);
System.out.println("被替换的元素是:"+old);
}
}
重载的add()和remove()方法
void add(int index,E e):将给定元素插入到index指定的位置
E remove(int index):删除并返回下标index处对应的元素
public class ListDemo2 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("one");
list.add("two");
list.add("three");
list.add("four");
list.add("five");
System.out.println(list);
/*
void add(int index,E e)
将给定元素插入到指定位置
*/
//[one,two,six,three,four,five]
list.add(2,"six");
System.out.println(list);
/*
E remove(int index)
删除并返回指定位置上的元素
*/
//[one,six,three,four,five]
String e = list.remove(1);
System.out.println(list);
System.out.println("被删除的元素:"+e);
}
}
subList()方法
List sublist(int start,int end):获取当前集合中start到end之间的子集(含头不含尾)
/**
* List subList(int start,int end)
* 获取当前集合中指定范围内的子集。两个参数为开始与结束的下标(含头不含尾)
*/
public class ListDemo3 {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
for(int i=0;i<10;i++){
list.add(i);
}
System.out.println(list);
//获取3-7这部分
List<Integer> subList = list.subList(3,8);
System.out.println(subList);
//将子集每个元素扩大10倍
for(int i=0;i<subList.size();i++){
subList.set(i,subList.get(i) * 10);
}
//[30,40,50,60,70]
System.out.println(subList);
/*
对子集元素的操作就是对原集合对应元素的操作
*/
System.out.println(list);
//删除list集合中的2-8
list.subList(2,9).clear();
System.out.println(list);
}
}
集合与数组的转换
集合转换为数组
Collection提供了一个方法:toArray,可以将当前集合转换为一个数组
/**
* 集合转换为数组
* Collection提供了方法toArray可以将当前集合转换为一个数组
*/
public class CollectionToArrayDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("one");
list.add("two");
list.add("three");
list.add("four");
list.add("five");
System.out.println(list);
// Object[] array = list.toArray();
/*
重载的toArray方法要求传入一个数组,内部会将集合所有元素存入该数组
后将其返回(前提是该数组长度>=集合的size)。如果给定的数组长度不足,
则方法内部会自行根据给定数组类型创建一个与集合size一致长度的数组并
将集合元素存入后返回。
*/
String[] array = list.toArray(new String[list.size()]);
System.out.println(array.length);
System.out.println(Arrays.toString(array));
}
}
数组转换为List集合
数组的工具类Arrays提供了一个静态方法asList(),可以将一个数组转换为一个List集合
/**
* 数组转换为List集合
* 数组的工具类Arrays提供了一个静态方法asList,可以将数组转换为一个List集合。
*/
public class ArrayToListDemo {
public static void main(String[] args) {
String[] array = {"one","two","three","four","five"};
System.out.println(Arrays.toString(array));
List<String> list = Arrays.asList(array);
System.out.println(list);
list.set(1,"six");
System.out.println(list);
//数组跟着改变了。注意:对数组转换的集合进行元素操作就是对原数组对应的操作
System.out.println(Arrays.toString(array));
/*
由于数组是定长的,因此对该集合进行增删元素的操作是不支持的,会抛出
异常:java.lang.UnsupportedOperationException
*/
// list.add("seven");
/*
若希望对集合进行增删操作,则需要自行创建一个集合,然后将该集合元素
导入。
*/
// List<String> list2 = new ArrayList<>();
// list2.addAll(list);
/*
所有的集合都支持一个参数为Collection的构造方法,作用是在创建当前
集合的同时包含给定集合中的所有元素
*/
List<String> list2 = new ArrayList<>(list);
System.out.println("list2:"+list2);
list2.add("seven");
System.out.println("list2:"+list2);
}
}
集合的排序
java.util.Collections类
Collections是集合的工具类,定义了很多静态方法用于操作集合
Collections.sort(List list)方法,可以对List集合进行自然排序(从小到大)
/**
* 集合的排序
* 集合的工具类:java.util.Collections提供了一个静态方法sort,可以对List集合
* 进行自然排序
*/
public class SortListDemo1 {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
Random random = new Random();
for(int i=0;i<10;i++){
list.add(random.nextInt(100));
}
System.out.println(list);
Collections.sort(list);
System.out.println(list);
}
}
排序自定义类型元素
/**
* 排序自定义类型元素
*/
public class SortListDemo2 {
public static void main(String[] args) {
List<Point> list = new ArrayList<>();
list.add(new Point(1,2));
list.add(new Point(97,88));
list.add(new Point(7,6));
list.add(new Point(9,9));
list.add(new Point(5,4));
list.add(new Point(2,3));
System.out.println(list);
/*
编译不通过的原因:
Collections.sort(List list)该方法要求集合中的元素类型必须实现接口:
Comparable,该接口中有一个抽象方法compareTo,这个方法用来定义元素之间比较
大小的规则.所以只有实现了该接口的元素才能利用这个方法比较出大小进而实现排序
操作.
*/
Collections.sort(list);//编译不通过 compare比较 comparable可以比较的
System.out.println(list);
}
}
实际开发中,并不会让自己定义的类(如果该类作为集合元素使用)去实现Comparable接口,因为这对我们的程序有入侵性。
侵入性:当我们调用某个API功能时,其要求我们为其修改其他额外的代码,这个现象就是入侵性。侵入性越强的API越不利于程序的后期可维护性,应当尽量避免。
重载的Collections.sort(List list,Comparator c)方法
/**
* 排序自定义类型元素
*/
public class SortListDemo2 {
public static void main(String[] args) {
List<Point> list = new ArrayList<>();
list.add(new Point(1,2));
list.add(new Point(97,88));
list.add(new Point(7,6));
list.add(new Point(9,9));
list.add(new Point(5,4));
list.add(new Point(2,3));
System.out.println(list);
/*
Collections.sort(List list)在排序List集合时要求集合元素必须实现了
Comparable接口。实现了该接口的类必须重写一个方法compareTo用与定义比较
大小的规则,从而进行元素间的比较后排序。否则编译不通过。
侵入性:
当我们调用某个API时,其反过来要求我们为其修改其他额外的代码,这种现象就
成为侵入性。侵入性不利于程序后期的维护,尽可能避免。
compare:比较
*/
// Collections.sort(list);
//匿名内部类的形式创建一个比较器
Comparator<Point> com = new Comparator<Point>() {
@Override
/**
* 实现比较器接口后必须重写方法compare.
* 该方法用来定义参数o1与参数o2的比较大小规则
* 返回值用来表示o1与o2的大小关系
*/
public int compare(Point o1, Point o2) {
int len1 = o1.getX() * o1.getX() + o1.getY() * o1.getY();
int len2 = o2.getX() * o2.getX() + o2.getY() * o2.getY();
return len1-len2;
}
};
Collections.sort(list,com);//回调模式
System.out.println(list);
}
}
最终没有侵入性的写法
/**
* 排序自定义类型元素
*/
public class SortListDemo2 {
public static void main(String[] args) {
List<Point> list = new ArrayList<>();
list.add(new Point(1,2));
list.add(new Point(97,88));
list.add(new Point(7,6));
list.add(new Point(9,9));
list.add(new Point(5,4));
list.add(new Point(2,3));
System.out.println(list);
/*
Collections.sort(List list)在排序List集合时要求集合元素必须实现了
Comparable接口。实现了该接口的类必须重写一个方法compareTo用与定义比较
大小的规则,从而进行元素间的比较后排序。否则编译不通过。
侵入性:
当我们调用某个API时,其反过来要求我们为其修改其他额外的代码,这种现象就
称为侵入性。侵入性不利于程序后期的维护,尽可能避免。
compare:比较
*/
// Collections.sort(list);
//匿名内部类的形式创建一个比较器
// Comparator<Point> com = new Comparator<Point>() {
// @Override
// /**
// * 实现比较器接口后必须重写方法compare.
// * 该方法用来定义参数o1与参数o2的比较大小规则
// * 返回值用来表示o1与o2的大小关系
// */
// public int compare(Point o1, Point o2) {
// int len1 = o1.getX() * o1.getX() + o1.getY() * o1.getY();
// int len2 = o2.getX() * o2.getX() + o2.getY() * o2.getY();
// return len1-len2;
// }
// };
// Collections.sort(list,com);//回调模式
// Collections.sort(list,new Comparator<Point>() {
// public int compare(Point o1, Point o2) {
// int len1 = o1.getX() * o1.getX() + o1.getY() * o1.getY();
// int len2 = o2.getX() * o2.getX() + o2.getY() * o2.getY();
// return len1-len2;
// }
// });
Collections.sort(list,(o1,o2)->
o1.getX() * o1.getX() + o1.getY() * o1.getY() -
o2.getX() * o2.getX() - o2.getY() * o2.getY()
);
System.out.println(list);
}
}
排序字符串
java中提供的类,如String,包装类都实现了Comparable接口,但有时候这些比较规则不能满足我们的排序需求时,同样可以临时提供一种比较规则来进行排序。
public class SortListDemo3 {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
// list.add("Tom");
// list.add("jackson");
// list.add("rose");
// list.add("jill");
// list.add("ada");
// list.add("hanmeimei");
// list.add("lilei");
// list.add("hongtaoliu");
// list.add("Jerry");
list.add("娃哈哈");
list.add("真不错");
list.add("哈哈哈哈");
System.out.println(list);
//按照字符多少排序
// Collections.sort(list);
// Collections.sort(list, new Comparator<String>() {
// public int compare(String o1, String o2) {
//// return o1.length()-o2.length();
// return o2.length()-o1.length();//反过来减就是降序
// }
// });
Collections.sort(list,(o1,o2)->o2.length()-o1.length());
System.out.println(list);
}
}