集合框架

1.集合框架的概念

集合:对象的容器,定义了多个对象进行操作的方法,类似数组的功能。可实现数组的功能。

与数组的区别:

  • 数组长度固定,集合长度不固定
  • 数组可以存储基本类型和引用类型,集合只能存储引用类型。

位置:java.util.*

Collection体系集合:

  • Collection是该体系结构的根接口,代表一组对象,称为集合。
  • List接口的特点:有序(添加顺序和遍历顺序一致)、有下标(可以像数组一样来访问)、元素可重复。
  • Set接口的特点:无序、无下标、元素不能重复。
  • 泛型和工具类:泛型和工具类是jdk1.5之后的特性,参数化类型,将类型作为参数进行传递。

在这里插入图片描述

2.Collection接口:父接口(根接口)

特点:代表一组任意类型的对象,总体来讲是无序、无下标、不能重复的。但是由于List接口存在,部分是有序有下标和元素可重复的。

常用的方法由代码作为示例:

//Collection集合的使用
public class Test{
    public static void main(String[] args)  {
        //创建集合;但是注意,由于Collection是接口,因此不能直接用new Collection创建,而需要到下层的类创建
        Collection collection = new ArrayList();
        //1.add:添加元素
        collection.add("西瓜");
        collection.add("草莓");
        collection.add("芒果");
        //输出元素个数和元素内容。注意元素个数不是length而是size。
        System.out.println("元素个数:"+collection.size());
        System.out.println(collection);
        //2.遍历集合
        //2.1 增强for,由于Collection集合整体而言是无序的所以不可以使用普通的for循环
        for (Object o : collection) {
            System.out.println(o);
        }
        System.out.println("------迭代器------");
        //2.2 使用迭代器Iterator
        Iterator it = collection.iterator();
        while (it.hasNext()){
            //这里我们是以字符串的方式输出每个元素,但是输出结果是Object类,所以我们需要进行强转。
            String s = (String) it.next();
            System.out.println(s);
            //由于迭代器中子带remove方法所以不可以直接使用colletion.remove来删除元素,直接通过Itrator对象调用remove方法即可
            it.remove();
        }
        System.out.println("元素个数"+collection.size());//输出结果为“元素个数0”
        //3.判断
        //判断一个集合是否包含某个元素
        System.out.println(collection.contains("西瓜"));
        //判端一个集合是否为空
        System.out.println(collection.isEmpty());
        //4.删除元素与清空元素
        //collection.remove("西瓜");
        //collection.clear();
    }
}

3.List接口与实现类

Collection的子接口,有序、有下标、元素可以重复,遍历可以使用普通for循环(因为有序,因此有下标)。

实现类:ArrayList、Linkedlist、Vector

List接口的使用

public class Test{
    public static void main(String[] args)  {
        //创建集合对象
        List list = new ArrayList();
        //1.添加元素。
        //由于集合的元素是引用类型,此处的数字其实是已经进行自动装箱的
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        System.out.println("元素个数:"+list.size());
        System.out.println(list);
        //2.删除操作
        //2.1通过角标删除
        list.remove(1);//2会被删除
        //2.2通过元素删除
        list.remove(new Integer(1));//数字1会被删除,若不是包装类则直接删除内容就可以不需要new。
        System.out.println(list);
        //3遍历元素
        //3.1 for遍历
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
        //3.2 增强for遍历
        for (Object o : list) {
            System.out.println(o);
        }
        //3.3 迭代器Iterator
        Iterator iterator = list.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
        //3.4 列表迭代器
        ListIterator lit = list.listIterator();
        //从前往后
        while (lit.hasNext()){
            System.out.println(lit.nextIndex()+":"+lit.next());
        }
        //从后往前
        while(lit.hasPrevious()){
            System.out.println(lit.previousIndex()+":"+lit.previous());
        }
        //4.判断
        System.out.println(list.contains(5));
        System.out.println(list.isEmpty());
    }
}

List实现类(1):Arraylist

Arraylist的使用和List基本一致,其存储结构为数组,查找和遍历速度较快,增删速度慢一些。添加元素、删除元素、遍历元素、与判断和List使用方式重合性较高,则代码主要演示其查找功能。

public class Test{
    public static void main(String[] args)  {
        //创建集合
        ArrayList arrayList = new ArrayList();
        //创建学生类并创建对象,然后在集合中添加元素
        Student s1 = new Student("张三",15);
        Student s2 = new Student("赵四",18);
        Student s3 = new Student("王五",20);
        arrayList.add(s1);
        arrayList.add(s2);
        arrayList.add(s3);
        //查找元素
        System.out.println(arrayList.indexOf(s2));
        //正常情况下这种方法是没办法得到和这个属性相同的元素的位置的,但是如果重写equals方法就可以。
        System.out.println(arrayList.indexOf(new Student("张三",15)));
        //重写后,删除也可以通过此方法进行删除
        arrayList.remove(new Student("赵四",18));
        System.out.println(arrayList);
    }
}

注意:重写equals方法时候,由于重写此方法使用很频繁,所以可以通过快捷键直接在我们创建类中进行重写。在Idea中Alt+inset会有选择equals和hashcode方法重写,选择则会直接出来。然后在主方法中则可以使用上述方法进行查找或者删除了。另外,由于我们是的元素是学生类,当遍历时候,主要要将元素类型强转为Student类。

List实现类(2):Vector

jdk1.0版本提供,运行效率慢,线程安全,数组结构,查询快,增删慢。(现在使用的较少,但是面试可能会考)不多说,直接上代码。

public class Test{
    public static void main(String[] args)  {
       //创建集合
        Vector vector = new Vector();
        //添加元素
        vector.add("草莓");
        vector.add("荔枝");
        vector.add("西瓜");
        System.out.println(vector);
        //遍历。是List的实现类,因此是有序的依然可以使用for循环和增强for循环。
        //但是Vector有独特的遍历方式:枚举器
        Enumeration elements = vector.elements();
        while (elements.hasMoreElements()){
            Object o = elements.nextElement();//或者使用String强转成字符串类型输出字符串
            System.out.println(o);
        }
        //判断和前面的方式一样,有contains、isEmpty
        //其他方法
        System.out.println(vector.firstElement());//输出第一个元素
        System.out.println(vector.lastElement());//输出最后一个元素
        System.out.println(vector.elementAt(2));//输出该坐标元素
    }
}

List实现类(3):LInkedList

LinkedList的使用方法和List完全一样,所以此处不多赘述,特别示范一个获取方法。

System.out.println(LinkedList.indexOf(1))//indexOf可以获取输入坐标的元素

4.泛型

Java泛型是jdk1.5中引入的一个新特性,其本质是参数化类型,把类型作为参数传递。

常见形式:泛型类、泛型接口、泛型方法。

语法:<T,…>T称为类型占位符,表示一种引用类型。

好处:

  • 提高代码的重用性
  • 防止类型转换异常,提高代码的安全性。

泛型类::泛型只能是引用类型,不同的泛型对象不能相互赋值。

格式:类型<泛型占位符,…>

public class Test {
    public static void main(String[] args) {
        //使用泛型类创建对象
        //由于是实例化,占位符要使用引用类型代替。此处将类型定为字符串类型
        MyGeneric<String> a = new MyGeneric<>();
        //由于对象是字符串类型,所以泛型类需要传入的内容是字符串类型
        //创建一个变量 
        a.t = "Hello";
        //调用方法
        a.show("大家好");
        //调用方法,将t作为返回值并输出
        String str = a.getT();
        System.out.println(str);
    }
}
class MyGeneric<T>{
    //1.创建变量
    T t;
    //可以用于创建变量,但是不可以用于实例化,因为无法保证传过来泛型类的构造方法一定能用。
    //2.泛型作为方法的参数
    public void show(T t){
        System.out.println(t);
    }
    //3.泛型作为方法的返回值
    public T getT(){
        return t;
    }
}

泛型接口:不能使用泛型创建静态常量。使用方式有两种:1.实现接口是确定类型。2.使用泛型类实现接口,然后在实例化对象的时候在确定类型。

  • 首先创建一个接口:
interface MyInterface<T>{
    T server (T t);
    //在没有使用T之前我们无法知道T是什么类型,因此不可以进行实例化
}
  • 方法1:在实现类阶段将实现类传入:
//在实现类接口阶段把实现类型传入,此处传入String类型
public class Test implements MyInterface<String>{
    @Override
    public String server(String s) {
        return s;
    }
}
  • 方法2:使用泛型类实现接口,等实例化对象的时候再确定类型
//使用泛型类实现接口,等实例化对象时再确定
public class Test01<T> implements MyInterface<T>{
    @Override
    public T server(T t) {
        return t;
    }
}
  • 下面进行测试:
public class Demo {
    public static void main(String[] args) {
        //方法1:
        Test impl1 = new Test();
        impl1.server("Hello");
        //方法2:
        Test01<String> impl2 = new Test01<>();
        impl2.server("Hi!");
    }
}

泛型方法:不需要传递数据类型,数据类型会根据传递的数据改变。

//泛型方法:语法:<T>方法返回值类型。调用方法时传递其类型
public class Test {
    public static void main(String[] args) {
        Test test = new Test();
        //T类型不需要自己传递,他会根据传递的数据自行决定
        test.show("Hello");
        test.show(1);
        test.show(2.14);
    }
    //创建泛型方法
    public<T> T show(T t){
        System.out.println("泛型方法"+t);
        //如果将T作为返回值类型,最后一定要加上返回值,如果返回值为void,后面这句返回值可以不加。
        return t;
    }
}

泛型集合:集合如果不使用泛型,则都是Object类型,那么我们在输出时,有时候就需要强转类型,就容易出错。

​ 概念:参数化类型,类型安全的集合,强制集合元素的类型必须一致。

​ 特点:1.编译时即可检查,而不是在运行时才抛出异常。

​ 2.访问时,不必类型转换(拆箱)。

​ 3.不同泛型之间引用不能相互赋值,泛型不存在多态。

import java.util.ArrayList;

//泛型集合
public class Fx {
    public static void main(String[] args) {
        //转换异常问题示范
        //首先定义一个Object类型的集合
        ArrayList<Object> arraylist1 = new ArrayList<>();
        arraylist1.add("XXX");
        arraylist1.add("10");
        //当集合内,有字符串类型,也有基本类型时候,进行强转时候,就一定会有一部分无法转换成另一种类型。就会出现类型转换异常。
        //此处遍历只能用Object类型遍历,否则就会报错。除非判断正确类型并进行强转才能避免。
        for (Object o : arraylist1) {
            System.out.println(o);
        }
        //而泛型将其类型确定后,就不再可以添加其他类型的元素了.遍历时也不再是Object类型了。
        ArrayList<String> arraylist2 = new ArrayList<>();
        arraylist2.add("xxx");
        arraylist2.add("yyy");
        for (String s : arraylist2) {
            System.out.println(s);
        }
        //当然,我们也可以传输自己定义的类型,但是元素也只能添加该类型的元素。
        //不同的类型不可以相互赋值,比如下面的例子,会报错
        //arraylist1 = arraylist2;
    }
}

5.Set接口与实现类

特点:无序、无下标、元素不可重复。

方法:全部继承Collection中的方法。

Set接口的使用

//Set接口的使用
public class Test {
    public static void main(String[] args) {
        //创建集合,由于Set是接口,所以需要使用其实现类创建新的对象
        Set<String> set = new HashSet<String>();
        //添加数据
        set.add("苹果");
        set.add("华为");
        set.add("小米");
        //由于其元素不可重复性,如果再次添加上述元素,则仍然只会输出三个元素。
        set.add("小米");
        System.out.println("数据个数:"+set.size());
        System.out.println("元素:"+set.toString());
        
        //删除数据。注:由于无序性,所以无法根据角标删除元素,只能根据元素值删除元素
        //remove是删除元素,clear是清空元素,不再演示
        
        //遍历:1、增强for。2、Iterator迭代器
        
        //判断:1、contains():是否包含某元素。2、isEmpty():集合是否为空。
    }
}

hashSet实现类

//存储结构:哈希表(数组+链表+红黑树)
//Set接口的使用,由于使用方法和Set使用基本一致,此处只做一些补充
public class Test {
    public static void main(String[] args) {
        //创建集合,由于Set是接口,所以需要使用其实现类创建新的对象
        HashSet<Person> persons = new HashSet<Person>();
        //添加数据
        Person p1 = new Person("尼可乐",26);
        Person p2 = new Person("里可",24);
        Person p3 = new Person("尼可",22);
        persons.add(p1);
        persons.add(p2);
        persons.add(p3);
        //不可以重复添加同一对象,但是可以创建不同的对象,具有相同元素。
        persons.add(new Person("尼可",22));
        System.out.println(persons.size());//此处为4
        //如果想要实现属性相同,则判定为同一对象,则可以在我们创建的类中重写hashCode和equals方法
        //快捷键:alt+insert--->equals&hashCode
        //重写后则遇到这种情况新添加的对象就不会被视为是新的元素了。
    }
}
//注意要先创建一个类供此处练习,我是创建了一个Person的类进行的练习。

TreeSet实现类

//TreeSet的使用
//存储结构:红黑树
public class Demo05 {
    public static void main(String[] args) {
        //创建集合
        TreeSet<String> treeSet = new TreeSet<>();
        //1.添加元素
        treeSet.add("xyz");
        treeSet.add("abc");
        treeSet.add("Hello");

        System.out.println("元素数量:"+treeSet.size());
        System.out.println(treeSet.toString());
        //2.删除:remove。清空:clear
        //3.1增强for遍历
        //3.2迭代器Iterator遍历
        //4.判断:contains。
    }
}

补充:

//使用TreeSet保存数据
public class Demo06 {
    public static void main(String[] args) {
        TreeSet<Person> persons = new TreeSet<>();
        Person p1 = new Person("尼可乐",26);
        Person p2 = new Person("里可",24);
        Person p3 = new Person("半引号",22);

        persons.add(p1);
        persons.add(p2);
        persons.add(p3);
        System.out.println("元素个数:"+persons.size());
        System.out.println(persons.toString());
        //不重写接口的方法会报错。
        //由于红黑树无法比较,需要实现Camparable接口,此接口中只有一个方法。重写这个方法,给他设定比较规则,就可以进行正常运行了

        //删除
        //遍历1.增强for 2.迭代器
        //判断
    }
}
//此处是提前创建了Person类。

实现Comparable接口方法如下,此接口中只有一个方法:compareTo,重写此方法。

 @Override
    public int compareTo(Person o) {
        int n1 = this.getName().compareTo(o.getName());
        int n2 = this.getAge() - o.age;
        //先按照姓名比再按年龄比。
        return n1 == 0 ? n2 : n1;
    }

实现定制比较:

//TreeSet的使用
//Comparator接口:实现定制比较(比较器)
public class Demo07 {
    public static void main(String[] args) {
        TreeSet<Person> persons = new TreeSet<>(new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                int n1 = o1.getAge() - o2.getAge();
                int n2 = o2.getName().compareTo(o2.getName());
                return  n1 == 0?n2:n1;
            }
        });
        Person p1 = new Person("尼可乐",26);
        Person p2 = new Person("里可",24);
        Person p3 = new Person("半引号",22);
        Person p4 = new Person("半引号",22);

        persons.add(p1);
        persons.add(p2);
        persons.add(p3);
        persons.add(p4);
        System.out.println(persons.toString());
        //此处输出只能输出三个元素
    }
}

案例:

//案例:使用TreeSet集合实现字符串按照长度进行排序
//comparator实现定制比较
public class Demo08 {
    public static void main(String[] args) {
        TreeSet<String> treeSet = new TreeSet<>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                int n1 = o1.length() - o2.length();
                int n2 = o1.compareTo(o2);
                return n1 == 0?n2:n1;
            }
        });
        //添加数据
        treeSet.add("Hellowolrd");
        treeSet.add("chengdu");
        treeSet.add("xian");
        treeSet.add("shanghai");
        treeSet.add("wuhan");
        treeSet.add("hubei");
        System.out.println(treeSet.toString());
    }
}

6.Map接口与实现类

map接口特点:

  • 用于存储任意键值对(key,value)
  • 键:无序、无下标、不允许重复
  • 值:无序、无下标、可以 重复

hashMap的使用

//Map接口的使用
//HashMap的使用1
public class Demo01 {
    public static void main(String[] args) {
        //创建Map集合
        Map<String,String> map = new HashMap<>();
        //1.添加元素
        map.put("cn","中国");
        map.put("us" ,"美国");
        map.put("uk","英国");
        //key不变但是value变了以后,value值会覆盖掉之前的value值。
        map.put("us","美利坚合众国");
        System.out.println("元素个数"+map.size());
        System.out.println(map.toString());

        //2.删除
        map.remove("us" );
        System.out.println("删除之后:"+map.size());

        //3.遍历
        //3.1使用keySet();返回值是所有key的set集合
        //使用keySet方法返回set集合,然后再用增强for遍历keySet获取key的值,再用get(key)获得value值
        Set<String> keyset = map.keySet();
        for (String key : keyset) {
            System.out.println(key+":"+map.get(key));
        }

        //3.2使用entrySet()方法,一个Entry就相当于一个键值对。
        Set<Map.Entry<String,String>> entries = map.entrySet();
        for (Map.Entry<String, String> entry : entries) {
            System.out.println(entry.getKey()+"="+entry.getValue());
        }

        //4.判断
        System.out.println(map.containsKey("cn"));
        System.out.println(map.containsValue("中国"));
    }
}
//HashMap集合的使用
//存储结构:哈希表(数组加链表)
//使用key的hashcode和equals作为重复
public class Demo02 {
    public static void main(String[] args) {
        //创建集合
        HashMap<Student,String> student = new HashMap<Student,String>();

        //1.添加元素
        Student s1 = new Student("ad",123);
        Student s2 = new Student("ap",234);
        Student s3 = new Student("tank",230);
        student.put(s1,"下路");
        student.put(s2,"中路");
        student.put(s3,"上路");
        //如果将元素的换掉值,输出结果值会覆盖。
        student.put(s3,"打野");

        //这样可以加进来,但是有时候会导致重复
        //重写hashCode和equals则不会加进来了。
        student.put(new Student("tank",230),"辅助");
        System.out.println("元素个数:"+student.size());
        System.out.println(student.toString());

        //2.删除:remove()

        //3.遍历
        //3.1使用keyset
        for (Student key : student.keySet()) {
            System.out.println(key+":"+student.get(key));
        }
        //3.2使用entrySet()
        for (Map.Entry<Student, String> entry : student.entrySet()) {
            System.out.println(entry.getKey()+"="+entry.getValue());
        }
        //4.判断:contains()
        //此时在判断中添加新的元素则会判断存在,因为重写了hashCode和equals方法。
    }
}
//此处提前创建了Student类

TreeMap的使用

public class Demo03 {
    public static void main(String[] args) {
        //新建集合
        //定制比较器。
        TreeMap<Student,String> treeMap = new TreeMap<Student,String>(new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return 0;
            }
        });
        //1.添加元素
        Student s1 = new Student("ad",123);
        Student s2 = new Student("ap",234);
        Student s3 = new Student("tank",230);
        //treeMap结构是红黑树,不可以直接进行添加元素。
        treeMap.put(s1,"下路");
        treeMap.put(s2,"中路");
        treeMap.put(s3,"上路");

        System.out.println("元素个数:"+treeMap.size());
        System.out.println(treeMap.toString());
        //2.删除remove

        //3.遍历
        //3.1 使用keySet
        for (Student key : treeMap.keySet()) {
            System.out.println(key+":"+treeMap.get(key));
        }
        //3.使用2entrySet()
        for (Map.Entry<Student, String> entry : treeMap.entrySet()) {
            System.out.println(entry.getKey()+":"+entry.getValue());
        }
        //4.判断contains
        //5.定制比较
    }
}

7.Collection工具类

//工具类的使用
public class ToolsClass {
    public static void main(String[] args) {
        //创建集合
        List<Integer> list = new ArrayList<>();
        list.add(2);
        list.add(5);
        list.add(7);
        list.add(9);
        list.add(1);
        //sort排序
        System.out.println("排序之前:"+list.toString());
        Collections.sort(list);
        System.out.println("排序之后:"+list.toString());
        //binarySearch二分查找
        int i = Collections.binarySearch(list, 12);
        System.out.println(i);//找不到则会输出负数

        //copy复制
        List<Integer> dest = new ArrayList<>();
        //由于copy方法要求两个集合容量要相等,所以需要做一个循环操作,使目标集合大小和原始集合容量相等
        for (int j = 0; j < list.size(); j++) {
            dest.add(0);
        }
        Collections.copy(dest,list);
        System.out.println(dest.toString());

        //reverse反转

        Collections.reverse(list);
        System.out.println("反转之后:"+list);

        //shuffle 打乱
        Collections.shuffle(list);
        System.out.println("打乱之后:"+list);

        //补充1:list转成数组
        Integer[] arr = list.toArray(new Integer[7]);
        //此处给的长度如果小于list长度,那么输出的长度和list相同,如果大于的话,则和给的长度相同
        System.out.println(arr.length);
        System.out.println(Arrays.toString(arr));

        //补充2:将数组转成集合
        String[] names = {"张三","王五","赵四"};
        //此集合为受限集合,不能删除或添加。
        List<String> list1 = Arrays.asList(names);
        System.out.println(list1);

        int[] nums = {01,20,30,40,50};
        //<>中如果是int[]那么数组中就不再是数字了,而是一个数据,一个数组
        List<int[]> list2 = Arrays.asList(nums);
        //所以基本类型转成数组时候不能使用int,而需要修改为包装类。
        Integer[] nums1 = {01,20,30,40,50};
        List<Integer> list3 = Arrays.asList(nums1);
        System.out.println(list3);
    }
}

8.总结

集合的概念:对象的容器,和数组类似,定义了多个对象进行操作的常用方法。
List集合:有序、有下标、元素可重复。(常用实现类:ArrayList、LinkedList、Vector)
Set集合:无序、无下标、元素不可重复(HashSet、TreeSet)
Map集合:存储一对数据,无序、无下标,键不可重复,值可重复。(HashMap、HashTable、TreeMap)
Collections:集合工具类,定义了除了存取以外的集合常用方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值