文章目录
ArrayList类
ArrayList:底层使用使用的是数组。查询快,增删慢 注意,此实现不是同步的 线程不安全 。效率高
元素有序的(存取顺序一致),元素编有索引 允许元素重复
ArrayList的特有功能:
JDK1.8新增的一个方法也能遍历集合
void forEach(Consumer<? super E> action) 执行特定动作的每一个元素的 Iterable直到所有元素都被处理或操作抛出异常
排序集合中的元素
void sort (Comparator < ? super E > c)
特有功能测试:
public class Test {
public static void main(String[] args) {
ArrayList list = new ArrayList();
list.add(100);
list.add(100);
list.add(200);
list.add(300);
list.add(400);
//遍历ArrayList集合:两种迭代器,for循环
//JDK1.8 提供的一种迭代方法,也能遍历集合
//void forEach(Consumer<? super E> action)
list.forEach(new Consumer() {
@Override
public void accept(Object o) {
//o就是集合中的元素
System.out.println(o);
}
});
}
}
public class Test1 {
public static void main(String[] args) {
//ArrayList的特有功能
ArrayList list = new ArrayList();
list.add(400);
list.add(300);
list.add(200);
list.add(100);
//void sort (Comparator < ? super E > c) 排序集合中的元素
//Comparator 比较器
list.sort(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
Integer a=(Integer)o1;
Integer b=(Integer)o2;
return a-b;
}
});
System.out.println(list);
System.out.println("=====================");
//boolean removeIf (Predicate < ? super E > filter) 删除集合中符合条件的元素
//删除集合中大于100的元素
list.removeIf(new Predicate() {
@Override
public boolean test(Object o) {
Integer num=(Integer)o;
return num>100;//返回true 就删除集合中的元素 返回false 就不删
}
});
System.out.println(list);
}
}
案例:去除ArrayList中重复自定义对象元素
public class Test3 {
public static void main(String[] args) {
//去除ArrayList中重复自定义对象元素
Student s1 = new Student("张三", 23);
Student s2 = new Student("李四", 24);
Student s3 = new Student("王五", 25);
Student s4 = new Student("张三", 23);
Student s5 = new Student("李四", 24);
Student s6 = new Student("王五", 25);
ArrayList list = new ArrayList();
list.add(s1);
list.add(s2);
list.add(s3);
list.add(s4);
list.add(s5);
list.add(s6);
//学生的姓名和年龄一模一样,是重复元素,需要去除
ArrayList list1 = new ArrayList();
for (int i=0;i<list.size();i++){
Object obj=list.get(i);
if (!list1.contains(obj)){
list1.add(obj);
}
}
for (int i=0;i<list1.size();i++){
System.out.println(list1.get(i));
}
}
}
案例:去除ArrayList中重复字符串元素
public class Test2 {
public static void main(String[] args) {
/*
需求:ArrayList去除集合中字符串的重复值(字符串的内容相同)
*/
//思路1:创建一个新的集合
ArrayList list = new ArrayList();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
list.add("eee");
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
ArrayList list1 = new ArrayList();
//遍历旧集合
for (int i = 0; i < list.size(); i++) {
Object o=list.get(i);
if (!list1.contains(o)){
list1.add(o);
}
}
System.out.println(list1);
//思路二:不创建新集合,采用选择排序的方式
for (int i=0;i<list.size()-1;i++){
for (int j=i+1;j<list.size();j++){
Object o=list.get(i);
//遇到相同元素就删掉
if (o.equals(list.get(j))){
list.remove(j);
j--;//记得减一下
}
}
}
System.out.println(list);
}
}
Vector类
A:Vector类概述: Vector 类可以实现可增长的对象数组 , Vector 是同步的。
B:Vector类特有功能
public void addElement(E obj)
public E elementAt(int index)
public Enumeration elements() Vector 集合中自己的一个迭代器
特有功能测试:
public class Test {
public static void main(String[] args) {
//Vector的特有功能
//public void addElement(E obj)
Vector vector=new Vector();
vector.add("aaa");
vector.add("bbb");
vector.addElement("ccc");
/*
E firstElement ()
返回此向量的第一个组件(位于索引 0)处的项)。
E lastElement ()
返回此向量的最后一个组件。*/
Object oo=vector.firstElement();
System.out.println(oo);//aaa
//public E elementAt(int index) 根据索引截取一个元素
Object obj=vector.elementAt(0);
System.out.println(obj);
System.out.println("====================");
//public Enumeration elements() Vector 集合中自己的一个迭代器
Enumeration enumeration=vector.elements();
//hasMoreElements() 判断还有没有下个元素
//nextElement() 获取下一个元素
while (enumeration.hasMoreElements()){
System.out.println(enumeration.nextElement());
}
}
}
LinkedList类
A:LinkedList类概述: List 接口的链接列表实现 , 此实现不是同步的
B:LinkedList类特有功能
public void addFirst(E e)及addLast(E e)
public E getFirst()及getLast()
public E removeFirst()及public E removeLast()
特有功能测试:
public class Test1 {
public static void main(String[] args) {
//LinkedList:底层数据结构是链表,查询慢,增删快,注意,此实现不是同步的。线程不安全,效率高
LinkedList lin = new LinkedList<>();
//public void addFirst(E e)及addLast(E e)
lin.addFirst(100);
lin.addFirst(200);
lin.addFirst(300);
lin.addFirst(400);
System.out.println(lin);
//public E getFirst()及getLast()
Object o=lin.getFirst();
Object o1=lin.getLast();
/* E removeFirst ()
移除并返回此列表的第一个元素。
E removeLast ()
移除并返回此列表的最后一个元素。*/
}
}
public class Test2 {
public static void main(String[] args) {
/* E poll ()
获取并移除此列表的头(第一个元素)
E pollFirst ()
获取并移除此列表的第一个元素;如果此列表为空,则返回 null。
E pollLast ()
获取并移除此列表的最后一个元素;如果此列表为空,则返回 null。*/
LinkedList linkedList = new LinkedList();
linkedList.addLast(100);
linkedList.addLast(200);
linkedList.addLast(300);
linkedList.addLast(400);
Object poll=linkedList.poll();
System.out.println(poll);
System.out.println(linkedList);
}
}
public class Test3 {
public static void main(String[] args) {
/* E pop ()
从此列表所表示的堆栈处弹出一个元素。
void push (E e)
将元素推入此列表所表示的堆栈。
*/
LinkedList linkedList = new LinkedList();
linkedList.add(100);
linkedList.add(200);
linkedList.add(300);
linkedList.add(400);
linkedList.push(600);
linkedList.push(800);
Object p=linkedList.pop();
System.out.println(p);//800
System.out.println(linkedList);
}
}
案例:用LinkedList模拟栈数据结构的集合并测试
public class MyStack {
private LinkedList linkedList;
public MyStack(){
linkedList=new LinkedList();
}
//添加元素的方法
public void addEle(Object obj){
linkedList.addFirst(obj);
}
//获取元素的方法
public Object getEle(){
Object o=linkedList.getFirst();
return o;
}
}
public class Test {
public static void main(String[] args) {
//请用LinkedList模拟栈数据结构的集合,并测试
MyStack myList=new MyStack();
myList.addEle(100);
myList.addEle(200);
myList.addEle(300);
Object o=myList.getEle();//300
Object o1=myList.getEle();//200
Object o2=myList.getEle();//100
System.out.println(o);
}
}
泛型
1.概述和基本使用
泛型的由来:通过Object转型问题引入
早期的Object类型可以接收任意的对象类型,但是在实际的使用中,会有类型转换的问题。
也就存在这隐患,所以Java提供了泛型来解决这个安全问题。
A:泛型类概述: 把泛型定义在类上
B:定义格式: public class 类名<泛型类型1,…>
C:注意事项: 泛型类型必须是引用类型
泛型只在编译期有效,在运行期就擦除了
D:泛型的好处:
把运行时期的问题提前到了编译期间
避免了向下转型,提高了代码的扩展性
public class Test {
public static void main(String[] args) {
//泛型机制:是一种将数据类型明确工作,推迟到创建对象或调用方法时才去明确的一种机制。
//没有使用泛型时,集合中可以存储多种引用数据类型
//在创建集合时使用泛型,明确集合中的数据类型
ArrayList<String> list = new ArrayList();
list.add("123");
String s=list.get(0);//避免了向下转型
//把泛型明确成Object,集合中可以存储多种数据类型
ArrayList<Object> objects = new ArrayList<>();
objects.add("abc");
objects.add(666);
objects.add(new Object());
}
//一般来说,不会在集合中存储多种数据类型
}
2,泛型类,接口,方法的使用
A:泛型类概述: 把泛型定义在类上
B:定义格式: public class 类名<泛型类型1,…>
C:注意事项: 泛型类型必须是引用类型
泛型只在编译期有效,在运行期就擦除了
D:案例演示: 泛型类的使用
//泛型定义在类上
public class MyClass2<E> {
public E obj;
public E getObj() {
return obj;
}
public void setObj(E obj) {
this.obj = obj;
}
}
public class Test2 {
public static void main(String[] args) {
MyClass2<String> myClass2 = new MyClass2();
myClass2.setObj("abc");
System.out.println(myClass2.getObj());
}
}
A:泛型方法概述: 把泛型定义在方法上
B:定义格式: public <泛型类型> 返回类型 方法名(泛型类型 变量名)
C:案例演示: 泛型方法的使用
public class CC {
//泛型方法,把泛型定义在方法上
public<T> void show(T t){
System.out.println(t);
}
}
public class Test1 {
public static void main(String[] args) {
CC cc = new CC();
cc.show("abc");
cc.show(3.14);
cc.show(100);
}
}
A:泛型接口概述: 把泛型定义在接口上
B:定义格式: public interface 接口名<泛型类型>
C:案例演示: 泛型接口的使用
public interface MyInterface<E> {
//泛型定义在接口上
public abstract void show(E e);
}
//有一个具体的子类,在实现一个接口时,这个接口上有泛型,就可以明确接口上的泛型的具体类型
public class MyClass1 implements MyInterface<String> {
@Override
public void show(String s){
System.out.println(s);
}
}
//子类在实现接口时,他没有急于去明确接口上的泛型,那么他自己就要定义成泛型类
public class MyClass<E> implements MyInterface<E> {
@Override
public void show(E e){
System.out.println(e);
}
}
public class Test {
public static void main(String[] args) {
MyClass<Integer> a = new MyClass();
a.show(50);//50
MyClass1 b=new MyClass1();
b.show("abc");//abc
}
}
3,泛型通配符
A:泛型通配符<?>: 任意类型,如果没有明确,那么就是Object以及任意的Java类了
B:? extends E: 向下限定,E及其子类
C:? super E: 向上限定,E及其父类
泛型通配符的使用:
public class GenericDemo {
public static void main(String[] args) {
//泛型如果明确写的时候,前后必须一致
Collection<Object> objects=new ArrayList<Object>();
Collection<?> objects1=new ArrayList<Object>();
//Collection<Object> o=new ArrayList<Animal>();报错
//Collection<Object> o1=new ArrayList<Dog>();报错
//Collection<Object> o2=new ArrayList<Cat>();报错
//? extends E 向下限定
Collection<? extends Animal> collection=new ArrayList<Animal>();
Collection<? extends Animal> collection1=new ArrayList<Cat>();
Collection<? extends Animal> collection2=new ArrayList<Dog>();
//? super E 向上限定
Collection<?super Animal> c=new ArrayList<Object>();
System.out.println("---------------------------------");
ArrayList<Integer> integers = new ArrayList<>();
integers.add(100);
ArrayList<Object> integers2= new ArrayList<>();
integers2.add(200);
/*boolean addAll (Collection < ? extends E > c)
按照指定 collection 的迭代器所返回的元素顺序,将该 collection 中的所有元素添加到此列表的尾部。*/
// boolean addAll (Collection < ? extends Integer > c) //向下限定
// integers.addAll(integers2); 报错,因为做了向下限定
}
}
class Animal{
}
class Dog extends Animal{}
class Cat extends Animal{}
增强for循环
A:增强for概述
简化数组和Collection集合的遍历
B:格式:
for(元素数据类型 变量 : 数组或者Collection集合) {
使用变量即可,该变量就是元素
}
C:案例演示
数组,集合存储元素用增强for遍历
D:好处和注意事项
新式for循环其实底层用的是迭代器遍历的
简化遍历
注意事项:增强for的目标要判断是否为null
注意新式for循环,你在迭代集合的途中,不能增删元素,会报并发修改异常
案例:ArrayList存储自定义对象并遍历增强for版
public class Test {
public static void main(String[] args) {
//增强for循环
/*
for(元素数据类型 变量 : 数组或者Collection集合) {
使用变量即可,该变量就是元素
}
* */
//ArrayList存储自定义对象并遍历增强for版
ArrayList<Student> objects = new ArrayList<Student>();
objects.add(new Student("张三",20));
objects.add(new Student("李四",21));
objects.add(new Student("王五",22));
for (Student student:objects){
System.out.println(student);
}
}
}
可变参数
A:可变参数概述: 定义方法的时候不知道该定义多少个参数
B:格式: 修饰符 返回值类型 方法名(数据类型… 变量名){}
C:注意事项:
a: 这里的变量其实是一个数组 可变参数其实是个数组,把你传过来的多个参数放到数组中
b: 如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个
可变参数的使用:
public class Test1 {
public static void main(String[] args) {
//可变参数 定义方法的时候不知道该定义多少个参数时使用
//格式:修饰符 返回值类型 方法名(数据类型… 变量名){}
int sum=add(1,2,3,4);
System.out.println(sum);//10
}
// 可变参数其实是个数组,把传过来的多个参数放到数组中
public static int add(int...i){
int sum=0;
for (int j:i){
sum+=j;
}
return sum;
}
//如果一个方法,定义了多个形参,可变参数一定是最后一个。
private static int add3(String num, double... i) {
return 0;
}
}
静态导入
//静态导入
/*
* 格式:import static 包名...类名.方法名
* 可以直接导入到方法的级别
*
* 注意事项:1.方法必须是静态的
* 2. 如果有多个同名的静态方法,要加前缀
*
* 一般不使用
* */
import static java.lang.Math.abs;
import static java.lang.Math.pow;
import static java.lang.Math.max;
public class StaticImportDemo {
public static void main(String[] args) {
System.out.println(Math.abs(-1));
System.out.println(Math.pow(2,3));
System.out.println(Math.max(1,2));
System.out.println(java.lang.Math.abs(-100));//如果有多个同名的静态方法,要加前缀
}
public static void abs(String s){
System.out.println(s);
}
}
集合嵌套之ArrayList嵌套ArrayList
A:需求:
我们班有学生,每一个学生是不是一个对象。所以我们可以使用一个集合表示我们班级的学生。ArrayList<Student>
但是呢,我们旁边是不是还有班级,每个班级是不是也是一个ArrayList<Student>。
而我现在有多个ArrayList<Student>。也要用集合存储,怎么办呢?
集合嵌套之ArrayList嵌套ArrayList
// 定义大的集合
ArrayList<ArrayList<Student>> allClassList = new ArrayList<ArrayList<Student>>() ;
// 创建每一个班的集合
ArrayList<Student> jcClassList = new ArrayList<Student>() ;
案例:嵌套存储并遍历学生对象
//集合嵌套之ArrayList嵌套ArrayList
public class Test {
public static void main(String[] args) {
ArrayList<ArrayList<Student>> aClass = new ArrayList<ArrayList<Student>>();
ArrayList<Student> javaClass1 = new ArrayList<Student>();
//学生进班
javaClass1.add(new Student("张三",20));
javaClass1.add(new Student("李四",21));
javaClass1.add(new Student("王五",20));
//把第一个班存储到学生系统中
aClass.add(javaClass1);
ArrayList<Student> javaClass2 = new ArrayList<Student>();
//学生进班
javaClass1.add(new Student("唐僧",20));
javaClass1.add(new Student("孙悟空",21));
javaClass1.add(new Student("猪八戒",20));
//把第二个班存储到学生系统中
aClass.add(javaClass2);
ArrayList<Student> javaClass3 = new ArrayList<Student>();
//学生进班
javaClass1.add(new Student("松江",20));
javaClass1.add(new Student("吴用",21));
javaClass1.add(new Student("高俅",20));
//把第三个班存储到学生系统中
aClass.add(javaClass3);
//用增强for循环遍历
for (ArrayList<Student> arrayList:aClass){
for (Student student:arrayList){
System.out.println(student);
}
}
}
}
Arrays工具类的asList()方法的使用
A:案例演示: Arrays工具类的asList(T... t)方法的使用: 将数组转换成集合
public static <T > List < T > asList(T...a)
注意事项: 得到的集合长度是不可变的 你不能往这个转换后的集合中 添加元素(add) 和 删除元素(remove)只能获取元素(get)
原因://这个方法的内部创建了一个 ArrayList
//这个ArrayList 是Arrays里面的一个内部类,不是我们之前学的java.utli包下的ArrayList
没有add和remove方法
public class MyTest {
public static void main(String[] args) {
/* Arrays工具类的asList(T...t)方法的使用:
将数组转换成集合*/
//泛型方法:方法上的泛型,是你在调用方法时,就可以明确方法上泛型的具体数据类型
/* static <T> List <T>
asList(T...a)
返回一个受指定数组支持的固定大小的列表。*/
//将多个参数,转换成集合
List<String> strings = Arrays.asList("abc", "bbb", "ccc", "dddd");
List<Integer> integers = Arrays.asList(100, 200, 300, 400);
System.out.println("============================");
int[] arr={10,20,30};
//当我传进来一个基本数据类型的数组,转换成的集合是这样的,集合里面放了一个数组
List<int[]> ints = Arrays.asList(arr);
int i = ints.get(0)[2];
System.out.println(i);
System.out.println(ints);
System.out.println("==================================");
//对象数组
Integer[] arr2= {10, 20, 30};
//当我传进来的是一个对象数组。他是怎么转换成集合的?他把数组中的元素取出来,再放到集合中
List<Integer> integers1 = Arrays.asList(arr2);
System.out.println(integers1.get(0));
System.out.println(integers1);
System.out.println("==========================");
int[] arr1 = {10, 20, 30};
int[] arr4= {10, 20, 30};
int[] arr3= {10, 20, 30};
//传进来多个元素是基本数据类型的数组,转换成的集合是,这个集合中,放了多个数组对象
List<int[]> ints1 = Arrays.asList(arr1, arr3, arr4);
System.out.println(ints1);
System.out.println("=========================================");
Integer[] arr5 = {10, 20, 30};
Integer[] arr6= {10, 20, 30};
Integer[] arr7 = {10, 20, 300};
//当你传进来,多个对象数组,那么就把这个对象数组,作为整体,放到集合中
List<Integer[]> integers2 = Arrays.asList(arr5, arr6, arr7);
System.out.println(integers2);
Integer integer = integers2.get(integers2.size()-1)[2];
System.out.println(integer);
}
}
0};
int[] arr4= {10, 20, 30};
int[] arr3= {10, 20, 30};
//传进来多个元素是基本数据类型的数组,转换成的集合是,这个集合中,放了多个数组对象
List<int[]> ints1 = Arrays.asList(arr1, arr3, arr4);
System.out.println(ints1);
System.out.println("=========================================");
Integer[] arr5 = {10, 20, 30};
Integer[] arr6= {10, 20, 30};
Integer[] arr7 = {10, 20, 300};
//当你传进来,多个对象数组,那么就把这个对象数组,作为整体,放到集合中
List<Integer[]> integers2 = Arrays.asList(arr5, arr6, arr7);
System.out.println(integers2);
Integer integer = integers2.get(integers2.size()-1)[2];
System.out.println(integer);
}
}