美文网首页
Java入门系列08 -- 泛型,集合

Java入门系列08 -- 泛型,集合

作者: YanZi_33 | 来源:发表于2021-11-12 22:18 被阅读0次

泛型

  • 从Java5开始,引入泛型技术;
  • 泛型:将类型变为参数,提高代码的复用率;
  • 建议使用的类型参数名称有:
    • T:Type
    • E:Element
    • K:Key
    • N:Number
    • V:Value
    • S,U,V:2nd,3rd,4th types
泛型类型
  • 泛型类型:使用了泛型的类或者接口;
public class Student<T> {
    private T scores;

    public Student(T scores) {
        this.scores = scores;
    }
}
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //分数参数 可以传任意类型
        //调用的时候 必须指定一个具体类型
        Student<String> student1 = new Student<String>("A");
        Student<Double> student2 = new Student<Double>(100.0);
        Student<Integer> student3 = new Student<Integer>(90);
        //右侧的泛型类型可以省略
        Student<Integer> student3 = new Student<>(90);
    }
}
  • 定义泛型之后,在调用时必须指定一种特定的类型;
泛型类型的继承
  • 案例代码:
public class Box<E>{
    private E element;

    public E getElement() {
        return element;
    }

    public void setElement(E element) {
        this.element = element;
    }
}
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //Box<String>与Box<Object> 之间没有继承关系
        Box<String> box1 = new Box<>();
        Box<Object> box2 = new Box<>();
        //报错
        //box2 = box1;

        box2.setElement(new Object());
        String str = box1.getElement();
    }
}
  • Box<String>与Box<Object> 之间没有继承关系;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Iterable<String> iterable = null;
        Collection<String> collection = null;
        List<String> list = null;
        ArrayList<String> arrayList = null;

        iterable = collection;
        collection = list;
        list = arrayList;
     }
}
  • Iterable<String>Collection<String>List<String>ArrayList<String>四种之间存在继承关系,如下所示:
image.png
  • 所以 使用父类指针指向子类对象,不会出现错误;
import java.util.List;

public interface YYList<E,T> extends List<E> {
    void  setNo(T no);
}
import java.util.List;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        List<String> list = null;
        YYList<String,Integer> yyList1 = null;
        YYList<String,Double> yyList2 = null;
        YYList<String,String> yyList3 = null;

        list = yyList1;
        list = yyList2;
        list = yyList3;
     }
}
  • 继承关系图下所示:
image.png
  • 自定义接口YYList<E,T>继承自Java类List<E>,虽然实例化时,T的类型不同,它们之间依然有继承关系,所以用父类指针指向子类对象,不会报错;
原始类型
  • 原始类型:没有传递具体的类型 给泛型 的类型参数;
public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //Box 称为Box<E> 的原始类型
        //使用原始类型 会出现警告,需要我们在使用泛型时 要指定一个类型
        Box rawBox = new Box();

        Box<String> boxStr = new Box<>();
        Box<Double> boxDou = new Box<>();

        rawBox = boxStr;
        rawBox = boxDou;

        boxStr = rawBox;
        boxDou = rawBox;
     }
}
  • Box 称为Box<E>原始类型
  • Box<Object>是非原始类型;
  • 当使用了原始类型时,编译器会给出rawtypes警告,可以使用@SuppressWarnings进行消除;
  • 非原始类型 赋值给 原始类型时,编译器没有任何警告和错误;
  • 将原始类型赋值给非原始类型时,编译器会给出unchecked警告,可以使用@SuppressWarnings进行消除;
泛型方法
  • 泛型方法:使用了泛型的方法(实例方法,静态方法,构造方法);
public class Student<N,S> {
    private N no;
    private S scores;

    public Student(N no,S scores) {
        this.no = no;
        this.scores = scores;
    }

    public N getNo() {
        return no;
    }

    public void setNo(N no) {
        this.no = no;
    }

    public S getScores() {
        return scores;
    }

    public void setScores(S scores) {
        this.scores = scores;
    }
}
public class MainActivity extends AppCompatActivity {

    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Student<String,Integer> student = new Student<>("1",100);
        set(student,"2",99);

        //出现报错
        Student<Integer,Double> student1 = new Student<>(5,77.5);
        //set(student1,66,44.5);
        sett(student1,5,89.5);
     }

     public static void set(Student<String,Integer> student,String no,Integer scores) {
        student.setNo(no);
        student.setScores(scores);
     }

     //属于泛型方法
     public static <T1,T2> void sett(Student<T1,T2> student,T1 no,T2 scores) {
         student.setNo(no);
         student.setScores(scores);
     }
}
  • 首先set方法,其参数的类型是写死的,只能接受student实例对象,若又要接受student1实例对象,出现类型冲突就会报错,可使用泛型方法settpublic static <T1,T2> void sett(Student<T1,T2> student,T1 no,T2 scores)
public class Box<E>{
    private E element;

    public Box() {}
    public Box(E element) {
        this.element = element;
    }

    public E getElement() {
        return element;
    }

    public void setElement(E element) {
        this.element = element;
    }
}
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        List<Box<Integer>> boxes = new ArrayList<>();
        addBox(11,boxes);
        addBox(22,boxes);
        addBox(33,boxes);

     }

     public static <T> void addBox(T element, List<Box<T>> boxes) {
        Box<T> box = new Box<>(element);
        boxes.add(box);
     }
}
泛型方法 -- 构造方法
public class YYPerson<T> {

    private T age;
    public <E> YYPerson(E name,T age) {

    }
}
public class MainActivity extends AppCompatActivity {

    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        YYPerson<Integer> person1 = new YYPerson("yanzi",10);
        YYPerson<Double> person2 = new YYPerson("23.9",33.6);
        YYPerson<String> person3 = new YYPerson<String>(11,"23");
     }
}
限制类型参数
  • 可以通过extends对类型参数增加一些限制条件,比如<T extends A>;
  • extends后面可以跟上类名,接口名,代表T必须是A类型,或者继承,实现A;
public class Person<T extends Number>{
    private T age;

    public T getAge() {
        return age;
    }

    public void setAge(T age) throws  Exception{
        if (age == null) {
            System.out.println("age不合理");
            //抛出异常
            throw new Exception("age必须>0");
        } else {
            this.age = age;
        }
    }
}
  • <T extends Number>:泛型T 只能是数字类型;
public class Person implements Comparable<Person>{
    private int age;

    public int getAge() {
        return age;
    }

    public Person(int age) {
        this.age = age;
    }

    public void setAge(int age) throws  Exception{
        if (age <= 0) {
            System.out.println("age不合理");
            //抛出异常
            throw new Exception("age必须>0");
        } else {
            this.age = age;
        }
    }

    @Override
    public int compareTo(Person o) {
        if (o == null) return 1;
        return age - o.age;
    }
}
import com.example.java_test.java.cls.Person;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Integer[] arr = {11,33,21,45,77,32};
        System.out.println("Main" + getMax(arr));

        Person[] ps = {new Person(11),new Person(22),new Person(66)};
        System.out.println("Main" + getMax(ps));
    }

    public static <T extends Comparable<T>> T getMax(T[] array) {
        if (array.length == 0 || array == null) return null;
        T max = array[0];
        for (int i = 1; i < array.length; i++) {
            if (array[i].compareTo(max) <= 0) continue;
            max = array[i];
        }
        return max;
    }
}
  • public static <T extends Comparable<T>> T getMax(T[] array):泛型方法,传入的数组元素 必须限制可以支持比较大小,即
  • 传入的Person对象数组,必须支持大小上的比较,需实现Comparable接口;
import com.example.java_test.java.cls.Person;
import java.util.Arrays;
import java.util.Comparator;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Person[] ps = {new Person(11),new Person(22),new Person(66)};
        Arrays.sort(ps, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.getAge() - o2.getAge();
            }
        });
    }
}
  • Comparator:是比较器;
public class Student<T extends Comparable<T>> implements Comparable<Student<T>>{
    private T scores;

    public Student(T scores) {
        this.scores = scores;
    }

    public T getScores() {
        return scores;
    }

    public void setScores(T scores) {
        this.scores = scores;
    }

    @Override
    public int compareTo(Student<T> o) {
        if (o == null) return 1;
        if (score != null) return scores.compareTo(o.scores);
        return o.scores != null ? -1 : 0;
    }
}
import com.example.java_test.java.cls.Student;


public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Student[] ss = {new Student(11),new Student(22),new Student(66)};
        System.out.println("Main" + getMax(ss));

    }

    public static <T extends Comparable<T>> T getMax(T[] array) {
        if (array.length == 0 || array == null) return null;
        T max = array[0];
        for (int i = 1; i < array.length; i++) {
            if (array[i].compareTo(max) <= 0) continue;
            max = array[i];
        }
        return max;
    }
}
  • public class Student<T extends Comparable<T>> implements Comparable<Student<T>>:Student支持可比较性,内部属性scores也支持可比较性;
通配符
  • 在泛型中,问号(?)被称为是通配符;
  • 通常用作变量类型,返回值类型的类型参数;
  • 不能用作泛型方法调用,泛型类型实例化,泛型类型定义的类型参数;
通配符 -- 上界
  • 通过extends设置类型参数的上界;
  • 类型参数必须是当前类型或者是当前类型的子类型;
public class Box<T> {

}
import com.example.java_test.java.cls.Box;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Box<Integer> box1 = new Box<>();
        Box<Double> box2 = new Box<>();
        Box<Object> box3 = new Box<>();

        //通配符 泛型中仅支持数字 可以是Integet,Double等等
        Box<? extends Number> box4 = null;

        showBox1(box1);
        showBox1(box2);
        showBox1(box3);
        showBox1(box4);

        showBox2(box1);
        showBox2(box2);
        showBox2(box3); //报错
        showBox2(box4);

        showBox3(box1);
        showBox3(box2);
        showBox3(box3); //报错
        showBox3(box4);
    }

    public static <T> void showBox1(Box<T> box) {

    }

    public static <T extends Number> void showBox2(Box<T> box) {

    }

    public static  void showBox3(Box<? extends Number>  box) {

    }
}
通配符 -- 下界
  • 可以通过super设置类型参数的下界;
  • 类型参数必须是当前类型或者当前类型的父类型
import com.example.java_test.java.cls.Box;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
     
        Box<Integer> b1 = new Box<>();
        Box<Number> b2 = new Box<>();
        
        testLower(b1);
        testLower(b2);
    }
    
    public static void testLower(Box<? super Integer> box) {} 
}
通配符 -- 无限制
import com.example.java_test.java.cls.Box;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Box<Integer> b1 = new Box<>();
        Box<Number> b2 = new Box<>();
        Box<String> b3 = new Box<>();

        test(b1);
        test(b2);
        test(b3);
    }

    public static void test(Box<?> box) {}
}
  • public static void test(Box<?> box):类型没有限制
通配符 -- 注意点
  • 编译器在解析List<E>.set(int index,E element)时,无法确定E的真实类型,会报错;
import java.util.List;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


    }

    public static void test1(List<Integer> list) {
        Integer obj = list.get(0);
        list.set(0,obj);
        list.set(0,list.get(0));
    }

    public static void test2(List<?> list) {
        Object obj = list.get(0);
        list.set(0,obj); //报错
        list.set(0,list.get(0));
    }

    public static <T> void test(List<T> list) {
        T obj = list.get(0);
        list.set(0,obj); //报错
        list.set(0,list.get(0));
    }
}
泛型的使用限制
  • 基本类型不能作为类型参数;
import java.util.HashMap;
import java.util.Map;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //报错
        Map<int ,char> map = new HashMap<>();
        Map<Integer, Character> map1 = new HashMap<>();
    }
}
  • 不能创建类型参数的实例;
  • 不能定义类型为类型参数的静态变量,也不能用在静态方法上;
public class Box<E> {
     private static E value; //报错
}
  • 类型参数不能与instanceof一起使用;
ArrayList<Integer> list = new ArrayList<>();
if (list instaceof ArrayList<Integer>) {

}
  • 不能创建带有类型参数的数组;
Box<Integer>[] boxs = new Box<Integer>[4]; //报错
Box<Integer>[] boxs = new Box[4]; //ok
  • 不能构成重载;
void test(Box<Integer> box) {

}

void test(Box<String> box) {

}
  • 不能定义泛型的异常类;
public class MyException<T> extends Exception {

}
  • catch的异常类型不能用类型参数;
public staic <T extends Exception> void test(Box<T> box) {
    try {

    } catch (T e) { //报错

    }
}

集合

  • java.util包中有个集合框架(Collections Framework),提供了一大堆常用的数据结构;
    • ArrayList,LinkedList,Queue,Stack,HashSet,HashMap等;
  • 数据结构是计算机存储,组织数据的方式,常见的数据结构有:线性结构,树形结构,图形结构;
集合框架预览
image.png
  • List的特点:
    • 可以存储重复的元素;
    • 可以通过索引访问元素;
    • 有记录元素的添加顺序;
  • Set的特点:
    • 不可以存储重复的元素;
    • 不可以通过索引访问元素;
    • 不记录元素的添加顺序;
数组的局限性
public class MainActivity extends AppCompatActivity {
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        int[] array = new int[4];
        array[0] = 0;
        array[1] = 1;
        array[2] = 2;
        array[3] = 3;
     }
}
  • 数组无法动态扩容,上述array只能存储不超过4个元素;
  • 操作元素的过程不够面向对象;
  • java.util.ArrayList是Java中动态数组,可以动态扩容,且封装了各种使用的数组操作;
ArrayList的基本使用
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ArrayList list = new ArrayList();
        //添加元素
        list.add(11);
        list.add(false);
        list.add(null);
        list.add(3.14);
        list.add(0,"yanzi");
        list.add('8');

        //获取元素索引
        System.out.println("Main" + list.indexOf(null));
        System.out.println("Main" + list.size());
        System.out.println("Main" + list);

        //移除
        list.remove(8);
        list.remove(1);
        //是否包含
        boolean isContains = list.contains(11);
     }
}
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ArrayList list1 = new ArrayList();
        //添加元素
        list1.add(11);
        list1.add(22);
        list1.add(33);
        list1.add(44);
        
        ArrayList<Integer> list2 = new ArrayList<>();
        list2.add(22);
        list2.add(44);
        
        //从list1中 删除list2 中元素以外的所有元素
        list1.retainAll(list2);
        
        //list1 [22,44]
     }
}
  • retainAll:从list1中 删除list2 中元素以外的所有元素;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ArrayList<Integer> list1 = new ArrayList();
        //添加元素
        list1.add(11);
        list1.add(22);
        list1.add(33);

        //实现将动态数组 --> 普通数组
        //arr是一个存储Object的数组
        Object[] arr = list1.toArray();
        for (Object obj : arr) {
            System.out.println("Main:" + obj.getClass());
        }
        //这么写 可以转成 存储Integer的数组
        Integer[] arr2 = list1.toArray(new Integer[0]);
     }
}
  • Integer[] arr2 = list1.toArray(new Integer[0]):将动态数组 转成 普通数组;
ArrayList的遍历
import java.util.ArrayList;
import java.util.Iterator;
import java.util.function.Consumer;

public class MainActivity extends AppCompatActivity {

    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ArrayList<Integer> list1 = new ArrayList();
        //添加元素
        list1.add(11);
        list1.add(22);
        list1.add(33);
        //经典
        int size = list1.size();
        for (int i = 0; i < size; i++) {
            System.out.println("Main:" + list1.get(i));
        }

        //迭代器
        Iterator<Integer> iterator = list1.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
        
        //for-each 下面的底层实现 本质就是上面的迭代器 实现方式 
        for (Integer i: list1) {
            System.out.println(i);
        }
        
        //四面四种写法等价 
        //函数式接口
        list1.forEach(new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) {
                System.out.println(integer);
            }
        });
        
        list1.forEach((i) -> {
            System.out.println(i);
        });

        list1.forEach((i) -> System.out.println(i));
        list1.forEach(System.out::println);
     }
}
  • 遍历 for -each格式如下:
for (元素类型 变量名 : 数组/Iterable) {

}
  • 实现了Iterable接口的对象,都可以使用for -each格式遍历元素,例如List,Set等等;
  • Iterable在使用for -each格式遍历元素,本质是使用了Iterator对象;
自定义Iterable,Iterator
import androidx.annotation.NonNull;
import java.util.Iterator;

public class ClassRoom implements Iterable<String>{

    private  String[] students;

    public ClassRoom(String... students) {
        this.students = students;
    }

    public String[] getStudents() {
        return students;
    }

    public void setStudents(String[] students) {
        this.students = students;
    }

    @NonNull
    @Override
    public Iterator<String> iterator() {
        return new ClassRoomIterator();
    }

    //内部类
    private class ClassRoomIterator implements Iterator<String> {

        private int cursor;

        @Override
        public boolean hasNext() {
            return cursor < students.length;
        }

        @Override
        public String next() {
            return students[cursor++];
        }
    }
}
  • ClassRoom 实现 Iterable接口,然后提供一个自定义的遍历器ClassRoomIterator
ArrayList的扩容原理
遍历的注意事项
  • 若希望在遍历元素的同时删除元素;
    • 请使用Iterator进行遍历;
    • 然后使用Iterator的remove方法进行删除元素;
  • 使用迭代器,forEach在遍历集合元素的时候,若使用了集合自带的方法修改了集合的长度(例如add,remove等方法)
    • 那么可能会抛出java.util.ConcurrentModificationException异常
import java.util.ArrayList;
import java.util.Iterator;

public class MainActivity extends AppCompatActivity {

    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ArrayList<Integer> list = new ArrayList<>();
        list.add(11);
        list.add(22);
        list.add(33);
        list.add(44);
        list.add(55);
        list.add(66);

        //一边遍历 -- 一边删除 会出现数组越界
//        int size = list.size();
//        for (int i = 0; i < size; i++) {
//            list.remove(i);
//        }

        //出现异常 ConcurrentModificationException
//        for (Integer e : list) {
//            list.remove(e);
//        }

        //本质同上
//        Iterator<Integer> iterator = list.iterator();
//        while (iterator.hasNext()) {
//            list.remove(iterator.next());
//        }

        //依然报错
//        list.forEach((object) -> {
//            list.remove(object);
//        });

        //正确写法
        //游标
        Iterator<Integer> iterator = list.iterator();
        while (iterator.hasNext()) {
            iterator.next();
            iterator.remove();
        }
     }
}
  • 迭代器,forEach在遍历数组元素时,内部会检测modCount是否发生变化,若发生变化就会抛出异常,而使用集合自身修改集合长度的方法就会改变modCount值;
ListIterator
  • ListIterator继承自Iterator,在Iterator的基础上增加了一些功能;
import java.util.ArrayList;
import java.util.ListIterator;

public class MainActivity extends AppCompatActivity {

    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        ArrayList<Integer> list = new ArrayList<>();
        list.add(11);
        list.add(22);
        list.add(33);

        ListIterator<Integer> iterator = list.listIterator();
        //从前往后遍历
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }

        //从后往前遍历
        while (iterator.hasPrevious()) {
            System.out.println(iterator.previous());
        }

        while (iterator.hasNext()) {
            //让数组中每个元素 + 55
            iterator.set(iterator.next() + 55);
        }

        //[100,11,200,100,22,200,100,33,200]
        while (iterator.hasNext()) {
            //让数组中每个元素 前后 分别插入 两个元素 100与200
            iterator.add(100);
            System.out.println(iterator.next());
            iterator.add(200);
        }
     }
}
函数式接口
  • Supplier函数式接口
import java.util.function.Supplier;

public class MainActivity extends AppCompatActivity {
    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //makeString()一定会调用
        String str = getFirstNotEmptyString("124",makeString());
    }

    public static String makeString() {
        return "sds";
    }

    public static String getFirstNotEmptyString(String s1,String s2) {
        if (s1 != null && s1.length() > 0) return s1;
        if (s2 != null && s2.length() > 0) return s2;
        return null;
    }
}
  • makeString()方法一定会被调用,现作如下优化;
import java.util.function.Supplier;

public class MainActivity extends AppCompatActivity {
    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        String sttr = getFirstNotEmptyString("123", new Supplier<String>() {
            @Override
            public String get() {
                return makeString();
            }
        });
    }

    public static String makeString() {
        return "sds";
    }

    @RequiresApi(api = Build.VERSION_CODES.N)
    public static String getFirstNotEmptyString(String s1, Supplier<String> supplier) {
        if (s1 != null && s1.length() > 0) return s1;
        String s2 = supplier.get(); 
        if (s2 != null && s2.length() > 0) return s2;
        return null;
    }
}
  • makeString()方法,只有在s1为空的情况下才会调用,由于Supplier是函数式接口,再优化如下:
import java.util.function.Supplier;

public class MainActivity extends AppCompatActivity {
    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //函数式接口
        String sttr = getFirstNotEmptyString("123", () -> makeString());
    }

    public static String makeString() {
        return "sds";
    }

    @RequiresApi(api = Build.VERSION_CODES.N)
    public static String getFirstNotEmptyString(String s1, Supplier<String> supplier) {
        if (s1 != null && s1.length() > 0) return s1;
        String s2 = supplier.get();
        if (s2 != null && s2.length() > 0) return s2;
        return null;
    }
}
  • Consumer函数式接口
import java.util.function.Consumer;

public class MainActivity extends AppCompatActivity {
    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        int[] nums = {11,22,33};
        foreach(nums, new Consumer<Integer>() {
            @Override
            public void accept(Integer integer) {
                System.out.println("Main:" + (integer + 100));
            }
        });

        //等价写法
        foreach(nums,(num) ->  System.out.println("Main:" + (num + 100)));
    }

    @RequiresApi(api = Build.VERSION_CODES.N)
    public static void foreach(int[] nums, Consumer<Integer> consumer) {
        if (nums == null) return;
        for (Integer num : nums) {
            consumer.accept(num);
        }
    }
}
import java.util.function.Consumer;

public class MainActivity extends AppCompatActivity {
    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        int[] nums = {11,22,33,44,566,778,8};
        foreach(nums,(n) -> {
            
        },(n) -> {
            
        });
    }

    @RequiresApi(api = Build.VERSION_CODES.N)
    public static void foreach(int[] nums, Consumer<Integer> c1,Consumer<Integer> c2) {
        if (nums == null || c1 == null || c2 == null) return;
        for (Integer num : nums) {
            c1.andThen(c2).accept(num);
        }
    }
}
  • Predicate函数式接口
import java.util.function.Predicate;

public class MainActivity extends AppCompatActivity {
    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        int[] nums = {11,22,33,44,566,778,8,66};
        //过滤奇数
        String str = join(nums,(n) -> (n & 1) == 0);
        System.out.println("Main:" + str);

        //过滤偶数
        String str3 = join3(nums,(n) -> (n & 1) == 0);
        System.out.println("Main:" + str);

        //两个条件同时满足 and
        String str1 = join2(nums,(n) -> (n & 1) == 0,(n) -> (n % 3 == 0));
        System.out.println("Main:" + str1);
    }

    @RequiresApi(api = Build.VERSION_CODES.N)
    public static String join(int[] nums, Predicate<Integer> p) {
        if (nums == null || p == null) return null;
        StringBuilder sb = new StringBuilder();
        for (int n: nums) {
            if (p.test(n)) {
                sb.append(n).append("_");
            }
        }
        sb.deleteCharAt(sb.length() - 1);
        return sb.toString();
    }

    @RequiresApi(api = Build.VERSION_CODES.N)
    public static String join2(int[] nums, Predicate<Integer> p1,Predicate<Integer> p2) {
        if (nums == null || p1 == null) return null;
        StringBuilder sb = new StringBuilder();
        for (int n: nums) {
            if (p1.and(p2).test(n)) {
                sb.append(n).append("_");
            }
        }
        sb.deleteCharAt(sb.length() - 1);
        return sb.toString();
    }

    @RequiresApi(api = Build.VERSION_CODES.N)
    public static String join3(int[] nums, Predicate<Integer> p) {
        if (nums == null || p == null) return null;
        StringBuilder sb = new StringBuilder();
        for (int n: nums) {
            if (p.negate().test(n)) {
                sb.append(n).append("_");
            }
        }
        sb.deleteCharAt(sb.length() - 1);
        return sb.toString();
    }
}
  • Function函数式接口
import java.util.function.Function;

public class MainActivity extends AppCompatActivity {
    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        String[] strs = {"123","34","43"};
        int result = sum(strs,(str) -> Integer.valueOf(str));

        //先String转Integer 然后Integer % 10
        int result1 = sum1(strs,(str) -> Integer.valueOf(str),(i) -> i % 10);
    }

    @RequiresApi(api = Build.VERSION_CODES.N)
    public static int sum(String[] strings, Function<String,Integer> f) {
        if (strings == null || f == null) return 0;
        int result = 0;
        for (String str : strings) {
            result += f.apply(str);
        }
        return result;
    }

    @RequiresApi(api = Build.VERSION_CODES.N)
    public static int sum1(String[] strings, Function<String,Integer> f1,Function<Integer,Integer> f2) {
        if (strings == null || f1 == null) return 0;
        int result = 0;
        for (String str : strings) {
            result += f1.andThen(f2).apply(str);
        }
        return result;
    }
}
LinkedList
HashSet
  • 元素无序的;
  • 元素不可重复;
LinkedHashSet
  • 在HashSet的基础上,记录了元素的添加顺序;
TreeSet
  • TreeSet要求元素必须具备可比较性,默认按照从小到大的顺序遍历元素;
  • 可自定义比较器,按照特定的规则进行排序;
HashMap (开发中常用的字典)
  • HashMap存储的是键值对,也可称字典;
  • 不可以存储重复的key,可以存储重复的value;
  • 不可以通过索引访问元素;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

public class MainActivity extends AppCompatActivity {
    @RequiresApi(api = Build.VERSION_CODES.N)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        HashMap<String,String> map = new HashMap<>();
        //添加键值对
        map.put("name","yanzi");
        map.put("age","33");
        map.put("height","175");
        map.put("weight","120");

        //移除键值对
        map.remove("height");

        //遍历键值对
        Set<Map.Entry<String,String>> entries = map.entrySet();
        for (Map.Entry<String,String> entry : entries) {
            System.out.println(entry.getKey() + "=" + entry.getValue());
        }

        map.forEach((key,value) -> {
            System.out.println(key + "=" + value);
        });

        Collection<String> values = map.values();
        for (String value: values) {
            System.out.println(value);
        }

        Set<String> keys = map.keySet();
        for (String key : keys) {
            System.out.println(key + "=" + map.get(key));
        }
    }
}
LinkedHashMap
  • 在HashMap的基础上,记录了元素的添加顺序;
TreeMap
  • TreeMap要求元素必须具备可比较性,默认按照从小到大的顺序遍历key;
Collections
  • java.util.Collections是一个常用的集合工具类,提供了很多实用的静态方法;
总结:
  • Set的底层是基于Map实现的;

相关文章

  • Java入门系列08 -- 泛型,集合

    泛型 从Java5开始,引入泛型技术; 泛型:将类型变为参数,提高代码的复用率; 建议使用的类型参数名称有:T:T...

  • 【Java 基础】Java 泛型简单入门

    Java 泛型简单入门 前言 自学疯狂Java书籍,认真学习过Java Collection 集合,学的似懂非懂;...

  • Java入门系列-19-泛型集合

    集合 如何存储每天的新闻信息?每天的新闻总数是不固定的,太少浪费空间,太多空间不足。如果并不知道程序运行时会需要多...

  • 泛型接口,类和通配符

    java零基础入门-高级特性篇(六) 泛型 中 泛型的使用位置,除了最常见的约束集合元素,还可以使用在接口,类,方...

  • 《Kotlin入门实战》CH8 | 泛型

    泛型 泛型是在Java5中引入的,泛型让集合框架可以重用代码,在没有泛型时候,集合框架中存储数据的类型都是Obje...

  • Java一泛型

    目录 一、设计背景 二、什么是泛型?泛型的作用? 三、泛型的原理 四、使用泛型 一、设计背景 Java集合(Col...

  • Java学习之_必备知识

    一、语言的入门及进阶 Java基础语法 OO编程思想 集合 IO 异常 泛型 反射 多线程 函数式 二、Web基础...

  • Java泛型总结

    Java泛型总结 泛型使用 从Java5开始引入了“参数化类型”的概念,允许在创建集合的时候指定集合元素的类型 J...

  • JDK1.5后增加了泛型,那么为什么要有泛型呢?我们该如何自定义

    本篇主要讲解java泛型的理解、集合中简单使用泛型、自定义泛型结构(包括类、接口、方法)。 一、什么是泛型? 通俗...

  • java泛型、泛型的基本介绍和使用

    现在开始深入学习java的泛型了,以前一直只是在集合中简单的使用泛型,根本就不明白泛型的原理和作用。泛型在java...

网友评论

      本文标题:Java入门系列08 -- 泛型,集合

      本文链接:https://www.haomeiwen.com/subject/htbozltx.html