欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java:集合、泛型、枚举、反射 学习笔记

程序员文章站 2022-07-15 16:25:45
...

集合、泛型、枚举、反射

一.集合

集合按照其存储结构可以分为两大类

  • java.util.Collection
  • java.util.Map

其他的集合接口,都是由这俩个接口派生出来的

Collection

  • List

  • Set

    SortedSet

  • Queue

Map

  • StortedMap

一.Collection接口

Collection类型集合必须要有的基本的方法:
//向集合中添加元素
boolean add(E e)

//把一个指定集合中的所有数据,添加到当前集合中
boolean addAll(Collection<? extends E> c)

//清空集合中所有的元素。
void clear()

//判断当前集合中是否包含给定的对象。
boolean contains(Object o)

//判断当前集合中是否包含给定的集合的所有元素。
boolean containsAll(Collection<?> c)

//判断当前集合是否为空。
boolean isEmpty()

//返回遍历这个集合的迭代器对象
Iterator<E> iterator()

//把给定的对象,在当前集合中删除。
boolean remove(Object o)

//把给定的集合中的所有元素,在当前集合中删除。
boolean removeAll(Collection<?> c)

//判断俩个集合中是否有相同的元素,如果有当前集合只保留相同元素,如果没有当前集合元素清空
boolean retainAll(Collection<?> c)

//返回集合中元素的个数。
int size()

//把集合中的元素,存储到数组中。
Object[] toArray()

//把集合中的元素,存储到数组中,并指定数组的类型
<T> T[] toArray(T[] a)
迭代器
java.util.Iterator 接口中,主要定义俩个方法:
  public interface Iterator {
      boolean hasNext();//返回当前迭代器中是否还有下一个对象
      Object next();//获取迭代器中的下一个对象
 }
例如:
  public static void main(String[] args) {
    Collection c1 = new ArrayList();
    c1.add("hello1");
    c1.add("hello2");
    c1.add("hello3");
    //获取c1集合的迭代器对象
    Iterator iterator = c1.iterator();
    //判断迭代器中,是否还有下一个元素
    while(iterator.hasNext()){
        //如果有的话,就取出来
        Object obj = iterator.next();
        System.out.println(obj);
    }

注意这种迭代器方式获取集合中的每一个元素,是Collection集合及其子类型集合通用的方式

除了使用迭代器遍历集合之外,使用JDK1.5及以上提供的增强for循环,也可以遍历集合。
foreach循环的格式:
for(变量类型 变量名 : 集合){
	//操作变量
}
例如:
public static void main(String[] args) {
    Collection<String> c1 = new ArrayList<>();
    c1.add("hello1");
    c1.add("hello2");
    c1.add("hello3");
    for(Object o:c1){
    	System.out.println(o);
    }
}

同时,使用foreach循环也可以遍历数组:
public static void main(String[] args) {
    int[] arr = {1,3,5,7,9};
    //每次循环,使用变量i接收数组中的一个数据
    for(int i : arr){
    	System.out.println(i);
    }
}
1.Collection:单列存放
1.List:有序可重复

1.1ArrayList

ArrayList 类中使用数组来实现数据的存储, 所以它的特点是就是:增删慢,查找快

1.2LinkedList:

增删快,查找慢

1.3Vector:

Vector 内部也是采用了数组来存储数据,但是 Vector 中的方法大多数都是线程安全的方法,所以在 多线并发访问的环境中,可以使用 Vector 来保证集合中元据操作的安全。

2.Set:无序不可重复

2.1HashSet:通过hash算法去重

java.util.HashSet 类的实现,主要依靠的是 HashMap

HashSet中元素不可重复,主要是靠对象的hashCode和equals方法来判断对象是否重复。

先比较hashCode值,如果值不同,则不是同一个对象,如果值相同,在进一 步通过equals进行比较

2.2TreeSet:按照指定的规则排序

2.2.1自然排序: 把放到TreeSet中的数据对应的类型实现一Comparable接口,那么这个类的俩个对象就是可以比较大小的

public interface Comparable<T> {
	public int compareTo(T o);
}

compareTo方法使用说明: int result = o1.compareTo(o2);
result 0:相同
result 1:o2在前o1在后 交换
result -1:o1在前 o2在后 不交换

public static void main(String[] args) {
    Set set = new TreeSet();
    set.add(3);
    set.add(5);
    set.add(1);
    set.add(7);
    for(Object obj : set){
    	System.out.println(obj);
    }
}
//输出结果:
1
3
5
7

2.2.2 客户端排序(比较器):在构建TreeSet的时候传递排序规则,java.util.Comparator 接口,是一个比较器接口,它的实现类可以对俩个对象作出大小的比较,即 使对象没有实现 Comparable 接口,也可以进行比较。compare(o1,o2)

public interface Comparator<T> {
	int compare(T o1, T o2);
}

比较器的使用规则: int result = compare(o1, o2);

​ 0: 相同
​ 1: o2在前o1在后(交换位置)

​ -1: o1在前 o2在后

二.Map集合

Collection类型集合中,每次存一个数据。

Map类型集合中,每次需要存一对数据,key-value(键值对)

  • key值必须是唯一的,value值允许重复
  • 键(key)和值(value)一一映射,一个key对应一个value
  • 在Map中,通过key值(唯一的),可以快速的找到对应的value值
1.Map实现类

代码中经常会用到的有: HashMap 、 HashTable 、 TreeMap LinkedHashMap

1.1 HashMap

存储数据采用的哈希表结构,元素的存取顺序不能保证一致。由于要保证键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。(重要,最常用)

1.2 HashTable

和之前List集合中的 Vector 的功能类似,可以在多线程环境中,保证集合中的数据的操作安全,类中的方法大多数使用了 synchronized 修饰符进行加锁。(线程安全)

1.3 TreeMap

该类是 Map 接口的子接口 SortedMap 下面的实现类,和 TreeSet 类似,它可以对key值进 行排序,同时构造器也可以接收一个比较器对象作为参数。支持key值的自然排序和比较器排序俩种方 式。(支持key排序)

TreeMap 的使用(自然排序):
public static void main(String[] args) {
    Map map = new TreeMap();
    map.put(4,"mary");
    map.put(2,"jack");
    map.put(1,"tom");
    map.put(3,"lucy");
    Set keys = map.keySet();
    for(Object key : keys){
    	System.out.println(key+" : "+map.get(key));
    }
}
    //运行结果:
    1 : tom
    2 : jack
    3 : lucy
    4 : mary
TreeMap 的使用(比较器排序):
public static void main(String[] args) {
    Comparator c = new Comparator() {
    @Override
   	 public int compare(Object o1, Object o2) {
        Integer k1 = (Integer) o1;
        Integer k2 = (Integer) o2;
        //注意,这里在默认的比较结果基础上加了一个符号,即原来返回的正数变负                数、返回的负数变正数
        return -k1.compareTo(k2);//(倒序)
     }
    };
    //构造器中传入比较器对象
    Map map = new TreeMap(c);
    map.put(4,"mary");
    map.put(2,"jack");
    map.put(1,"tom");
    map.put(3,"lucy");
    Set keys = map.keySet();
    for(Object key : keys){
    	System.out.println(key+" : "+map.get(key));
    }
}
//运行结果:
4 : mary
3 : lucy
2 : jack
1 : tom

1.4LinkedHashMap

该类是 HashMap 的子类,存储数据采用的哈希表结构+链表结构。通过链表结构可 以保证元素的存取顺序一致;(存入顺序就是取出顺序)

LinkedHashMap 的使用:
public static void main(String[] args) {
    Map map = new LinkedHashMap();
    map.put(4,"mary");
    map.put(2,"jack");
    map.put(1,"tom");
    map.put(3,"lucy");
    Set keys = map.keySet();
    for(Object key : keys){
    	System.out.println(key+" : "+map.get(key));
    }
}
//运行结果:
4 : mary
2 : jack
1 : tom
3 : lucy
2.Map的遍历
public static void main(String[] args) {
    Map map = new LinkedHashMap();
    map.put(4,"mary");
    map.put(2,"jack");
    map.put(1,"tom");
    map.put(3,"lucy");
    Set entrySet = map.entrySet();
    for(Object obj : entrySet){
        Map.Entry entry = (Map.Entry) obj;
        System.out.println(entry.getKey()+" : "+entry.getValue());
    }
}
//运行结果:
4 : mary
2 : jack
1 : tom
3 : lucy

三.集合工具类

Collections 中的常用方法:

  • fill方法,使用指定元素替换指定列表中的所有元素

    List list = new ArrayList();
    list.add(1);
    list.add(2);
    list.add(3);
    Collections.fill(list, 20);
    for(Object o:list){
    	System.out.println(o);
    }
    
  • max方法,根据元素的自然顺序,返回给定集合的最大元素

    List list = new ArrayList();
    list.add(1);
    list.add(9);
    list.add(3);
    System.out.println(Collections.max(list));
    
  • min方法,根据元素的自然顺序,返回给定集合的最小元素

  • reverse方法,反转集合中的元素

    List list = new ArrayList();
    list.add(1);
    list.add(9);
    list.add(3);
    Collections.reverse(list);
    for(Object o:list){
    	System.out.println(o);
    }
    
  • sort方法,根据元素的自然顺序,对指定列表按升序进行排序

    List list = new ArrayList();
    list.add(1);
    list.add(9);
    list.add(3);
    //如果需要,也可以在第二个参数位置传一个比较器对象
    //Collections.sort(list,c);
    Collections.sort(list);
    for(Object o:list){
    	System.out.println(o);
    }
    
  • shuffle方法,使用默认随机源对指定列表进行置换

  • addAll方法,往集合中添加一些元素

二.范型

使用范型代表任意一种数据类型 范型声明后才能使用,声明几个范型,就是使用几个范型,要么一起用,要么不用

1.定义范型类
 [修饰符] class  Point<V1,V2>{
  V1 value1;
  V2 value2;
 }

构建对象的时候,对象引用上添加范型
Point<Integer,String> p = new XX();

2.定义范型接口
 [修饰符] interface  Point<X,Y>{
    public Y getX(X x);
  }
  • 给范型接口提供实现类或者自接口的时候给范型类型(不常用)

  • 给范型提供自接口或者是实现类的时候不给定具体的类型,还是用范型表示,当我们构建接口的实现类对象的时候在给定具体的类型

3.定义范型方法

当你写一个方法的时候,类上没有声明范型,但是方法中还想要使用范型,这时我们可以把方法声明成一个范型方法:传递什么类型返回什么类型

 class className{
  [修饰符] <T> T 方法名(T t){}
 }
  • 范型的语法规则:

    1.声明和构建的时候保持范型类型一致(必须保证范型一摸一样)

    2.申明范型的时候前面的引用添加范型,构建对象的范型可以省略
    (范型只在编译阶段起作用,运行时会被去除)

三.枚举

交通信号灯:
     public class Led{
      public static Led  RED= new Led();
      public static Led yellow=new Led();
      Public static Led green = new Led();
      String color;
      private Led(){}
     }
Test:
    main(){
      Led red =Led.red;
    }

枚举类:会将这个类能够构建的对象在这个类的第一行声明出来 枚举类构造器 私有的

枚举类的声明语法
[修饰符] enum 类名{
    //枚举类必须在【第一行】把这个类所有的对象生声明出来
    //枚举类所有的构造器都是私有的
    //定义属性
    //定义方法
 }

枚举类的实质:
一旦使用enum声明一个类,那么这个类会默认继承Enum类

public enum Color {
	BLACK, WHITE
}

四.反射

1.Student类如何产生:

​ 所有的学生共同拥有的特性使用Java语言表示称一个类 因此这个类就可以用来描 述Java中任何一个Student学生
​ 由这个类产生的对象就是一个具体学生

2.Teacher类如何产生:

​ 所有的老师共同拥有的特性使用Java语言表示称一个类
​ 因此这个类就可以用来描述Java中任何一个老师特性
​ 由这个类产生的对象就是一个具体老师

3.Student类 Teacher类

3.1共性:包 修饰符 类名 继承父类 实现接口 属性 方法 构造器
3.2Class :这个类是总结了Java所有的类/接口具备的特性,抽象而成的一个类,因此这 个类可以用来描述Java中任意一个类,Class类产生的对象就是Java中的某个具体类

使用Class类的对象来表示基本类型:
public static void main(String[] args)throws Exception {
    //这个对象c就代表java中的int类型
    Class c = int.class;
    //判断对象c所代表的类型是否是基本类型
    System.out.println(c.isPrimitive());
    //获取对象c所代表的类型的名字
    System.out.println(c.getName());
}
//运行结果:
true
int
使用Class类的对象来表示类类型:
public static void main(String[] args)throws Exception {
    //这个对象c就代表Student类
    Class c = Student.class;
    System.out.println(c.getName());
}
//运行结果:
com.briup.demo.Student
使用Class类的对象来表示接口类型:
public static void main(String[] args)throws Exception {
    //这个对象c就代表List接口类型
    Class c = List.class;
    System.out.println(c.isInterface());
    System.out.println(c.getName());
}
//运行结果:
true
java.util.List
使用Class类的对象来表示数组类型:
public static void main(String[] args)throws Exception {
	//这个对象c代表数组类型
    Class c;
    c = int[].class;
    c = int[][].class;
    c = Student[].class;
    System.out.println(c.isArray());
    System.out.println(c.getSimpleName());
    //返回组成该数组具体类型是什么
    System.out.println(c.getComponentType().getSimpleName());
}
//运行结果:
true
Student[]
Student

获取Class对象

java中的每种类型,都有且只有唯一的一个Class类型对象与之对应!并且在类加载的时候自动生成!

获取基本类型的Class对象:

只有一种方式: Class c = int.class;

获取接口类型的Class对象:

有俩种方式:

  • Class c1 = Action.class;
  • Class c2 = Class.forName(“com.briup.demo.Action”);

获取数组类型的Class对象:

有俩种方式:

  • Class c1 = int[].class;
  • int[] arr = new int[4]; Class c2 = arr.getClass();

获取类类型的Class对象:

有三种方式:

  • Class c1 = Student.class;
  • Class c2 = Class.forName(“com.briup.demo.Student”);
  • Student stu = new Student(); Class c3 = stu.getClass();

3.3属性: 修饰符 数据类型 属性名 属性值
3.4Filed:这个类是总结了Java所有的属性共同具备的特性,所以这个类就是用来描述 Java中任意一个属性,产生的对象某个具体属性

3.5Method:修饰符 返回类型 方法名 参数列表 抛出异常 返回值
这个类是总结了Java所有的方法共同具备的特性,所以这个类就是用来描述Java中任意一个方法,产生的对象某个具体方法

3.6构造器: 修饰符 方法名 参数列表
3.7Constructor: 这个类是总结了Java所有的构造器共同具备的特性,所以这个类
就是用来描述Java中任意一个构造器,产生的对象某个具体构造器

4.反射调用方法
public static void main(String[] args)throws Exception {
    Student stu = new Student();
    Class c = stu.getClass();
    //获取类中的toString方法,没有参数,这是从父类继承的方法
    Method m1 = c.getMethod("toString", null);
   
    //反射的方式,调用stu对象中的这个方法,没有参数,并接收执行结果
    //相当于之前的:Object result = stu.toString();
    Object result = m1.invoke(stu,null);
   
    //输出执行结果
    System.out.println(result);
    System.out.println("-------------------");
   
    //获取类中的sayHello方法,需要一个String类型的参数,这是自己定义的方法
    Method m2 = c.getMethod("sayHello", String.class);
   
    //反射的方式,调用stu对象中的这个方法,参数是"tom",并接收执行结果
    //相当于之前的:Object result = stu.sayHello("tom");
    result = m2.invoke(stu,"tom");
    
    //输出执行结果
    System.out.println(result);
}