集合(list、set、map)

集合

1、集合和数组的区别

(1)长度:

集合长度可变,数组长度固定。

(2)存储的元素类型:

  • 集合中存储的只能是引用数据类型,数组可以是基本数据类型和引用数据类型(类、接口类型、数组类型、枚举类型、注解类型,字符串型),但是只能存储一种类型的数据。
  • 集合在没有指定泛型之前,默认保存的是任意类型的元素(Object类型),指定泛型之后可以保存对应类型的元素
  • 数组存储引用类型的数据较为繁琐,使用集合更简洁
  • 数组比较适合保存基本类型的元素,集合比较适合保存引用类型的元素

2、集合的体系

(1)集合的体系

List接口与Set接口的不同:

  • List可以存储相同的元素,Set不能存储相同的元素。
  • Set元素无序,List有序

java的集合分为collection接口(单列集合)和Map(双列集合)两种体系,list和set是继承自collection的接口,map是一个独立的接口

list接口和set接口都有自己的实现类,因为接口是没有具体实现的,接口是一个规范,实现类在规范的基础上有自己的特性。在接口的实现上可以体现出面向对象编程的多态的特性。

(2)Collection 和 Collections的区别

  • Collections是个java.util下的类,它包含有各种有关集合操作的静态方法

排序:

  public static void main(String[] args) {
        List<Integer> list=new ArrayList<>();
        list.add(123);
        list.add(1);
        list.add(122);
        list.add(22);
        Collections.sort(list);
        for (int i = 0; i < list.size(); i++) {//类中的size方法
            System.out.println(list.get(i));
        }
    }
1
22
122
123

求最大值:

public class Test {
    public static void main(String[] args) {
        List<Integer> list=new ArrayList<>();
        list.add(123);
        list.add(1);
        list.add(122);
        list.add(22);
        System.out.println( Collections.max(list));
    }
}
123

Collection是个java.util下的接口,它是各种集合结构的父接口,如:list、set、map

 (3)Map接口

ArrayList集合

ArratList集合:查找快,增删慢的可变大小。

1、基本数据类型和引用数据类型的对应关系

因为集合只能存储引用数据类型,所以要注意基本数据类型和引用数据类型的对应关系:

与基本数据类型不同的是,基本数据类型所对应的包装类封装的有自己的方法,因此,功能上更加强大。

 

 2、ArrayList类中的常用方法

 

3、Arraylist集合的运用

创建Person类:

public class Person {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if (age >= 0 || age <= 200)
            this.age = age;
    }

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

用add、get方法实现添加和获取集合元素,结合size方法,实现集合的遍历:

import java.util.ArrayList;
public class Way {
    public void addPerson(ArrayList<Person> array) {

        Person p1 = new Person("张三", 12);
        Person p2 = new Person("李明", 14);
        Person p3 = new Person("李华", 23);
        Person p4 = new Person("吴佩佩", 2);
        Person p5 = new Person("王涛", 15);
        array.add(p1);//类中的add方法
        array.add(p2);
        array.add(p3);
        array.add(p4);
        array.add(p5);
    }

    // 运用一般的get()方法遍历集合
    public void printPerson(ArrayList<Person> array) {
        for (int i = 0; i < array.size(); i++) {//类中的size方法
            Person p = array.get(i);//get方法
            System.out.println(p.getName() + "  " + p.getAge());
        }
    }

}

测试类:

import java.util.ArrayList;
public class ArrayListDemo {
public static void main(String[] args) {
    ArrayList<Person> array=new ArrayList<Person>();
    Way way=new Way();
    way.addPerson(array);
    way.printPerson(array);
}
}

LinkedList集合

LinkedList集合的存储结构为链表,添加、删除快,查找慢,LinkedList和ArrayList的父类都是List接口,因此他们有很多相同的方法。

1、List共有方法

创建Person类:

public class Person {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if (age >= 0 || age <= 200)
            this.age = age;
    }

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

写遍历集合的方法:

import java.util.LinkedList;

public class Way {
    public void addPerson(LinkedList<Person> array) {

        Person p1 = new Person("张三", 12);
        Person p2 = new Person("李明", 14);
        Person p3 = new Person("李华", 23);
        Person p4 = new Person("吴佩佩", 2);
        Person p5 = new Person("王涛", 15);
        array.add(p1);//类中的add方法
        array.add(p2);
        array.add(p3);
        array.add(p4);
        array.add(p5);
    }

    // 运用一般的get()方法遍历集合
    public void printPerson(LinkedList<Person> link) {
        for (int i = 0; i < link.size(); i++) {//类中的size方法
            Person p = link.get(i);//get方法
            System.out.println(p.getName() + "  " + p.getAge());
        }
    }

}

测试类:

import java.util.LinkedList;
public class LinkedListDemo {
public static void main(String[] args) {
    LinkedList<Person> link=new LinkedList<Person>();
    Way way=new Way();
    way.addPerson(link);
    way.printPerson(link);
}
}

2、特有方法

 由于LinkedList具有查询慢,增删快的特性,为了充分利用它的特点,LinkedList集合还有很多特有的方法。

(1)addFirst方法:

package pers.zhb.LinkedList;

import java.util.Iterator;
import java.util.LinkedList;

public class Way {
    public void LinkedListPrint(LinkedList<Integer> link) {
        System.out.println("迭代器方法遍历集合:");
        Iterator<Integer> linkIt = link.iterator();// 获取集合的实现类对象,并调用集合的iterator()
        while (linkIt.hasNext()) {
            Integer in = linkIt.next();
            System.out.print(in);
        }
    }

    public void linkedListadd(LinkedList<Integer> link) {
        Integer it1 = new Integer(1);
        Integer it2 = new Integer(2);
        Integer it3 = new Integer(3);
        Integer it4 = new Integer(4);
        link.addFirst(it1);
        link.addFirst(it2);
        link.addFirst(it3);
        link.addFirst(it4);
    }

}
package pers.zhb.LinkedList;

import java.util.LinkedList;

public class LinkedListDemo {
    public static void main(String[] args) {
        LinkedList<Integer> link = new LinkedList<Integer>();
        Way way = new Way();
        way.linkedListadd(link);
        way.LinkedListPrint(link);
    }

}

由结果可知,LinkedList集合的addFirst集合符合“后进先出”的规则,具有栈的特点。

 (2)removeFirst()与getFirst():

package pers.zhb.LinkedList;

import java.util.LinkedList;

public class LinkedListDemo {
    public static void main(String[] args) {
        LinkedList<Integer> link = new LinkedList<Integer>();
        Way way = new Way();
        way.linkedListadd(link);
        link.removeFirst();// 方法removeFirst();
        System.out.println("集合中的第一个元素为:" + link.getFirst());// 方法getFirst();
        way.LinkedListPrint(link);
    }

}

(3)pop()、push()、isEmpty()方法的使用:

package pers.zhb.LinkedList;
import java.util.LinkedList;
public class LinkedListDemo {
    public static void main(String[] args) {
        LinkedList<Integer> link = new LinkedList<Integer>();
        Way way = new Way();
        way.linkedListadd(link);
        System.out.println("栈顶插入元素前,栈中的元素为:");
        way.LinkedListPrint(link);
        link.push(5);
        System.out.println();
        System.out.println("弹出栈顶的元素:" + link.pop());
        System.out.println("栈顶弹出元素后,栈中的元素为:");
        way.LinkedListPrint(link);
        System.out.println();
        System.out.println("是否为空:" + link.isEmpty());
    }
}

HashSet集合

HashSet集合的底层数据结构为哈希表,当存储已有类型的数据时,不需要重写equals和hashcode方法,如果存储自定义类型的数据需要将两个方法重写。存储过程中,先调用hashcode方法产生哈希值,根据哈希值寻找存储位置,如果两个数的哈希值相同,则调用equals方法,如果返回true则第二个元素不予存储(已经重复),否则,将其存储到哈希表中。

1、存储已经定义的数据:

import java.util.HashSet;
import java.util.Iterator;

public class HashSetDemo {
    public static void main(String[] args) {
        HashSet<String> hs = new HashSet<String>();
        hs.add("qwe");
        hs.add("123qwe");
        hs.add("q23we");
        hs.add("qw1e");
        hs.add("qwe");
        Iterator<String> it = hs.iterator();
        while (it.hasNext()) {
            String s = it.next();
            System.out.println(s);
        }

    }
}

由运行结果可知,不用重写equals和hashcode方法,即可去除重复元素。

2、存储自定义类型的数据(重写equals和hashcode方法)

创建Person类,重写equals和hashcode方法:

public class Person {
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if (age >= 0 || age <= 200)
            this.age = age;
    }

    public int hashCode() {//哈希值
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (!(obj instanceof Person)) {
            System.out.println("类型错误");
            return false;
        }
        Person other = (Person) obj;
        return this.age == other.age && this.name.equals(other.name);
    }

}

hashCode的重写原则:

  • 和属性相关、属性一样的话要求哈希值一样
  • 如果hashCode方法的重写有失误会造成哈希值一样的元素增多,那么就会造成equals执行的次数增加,使得程序的执行效率降低,因此,在属性不一样的情况下要尽最大努力让哈希值不一样
  • 选择系数的时候要尽量选择较大的系数,因为如果计算出来的hash地址越大冲突就会减少,查找起来的效率就会越高
  • 31占5bit,相乘造成数据溢出的概率较小
  • i*31可以转化为位移运算和减法运算,可以提高算法效率

创建Way类,添加数据、遍历集合:

import java.util.HashSet;
import java.util.Iterator;

public class Way {
    // 添加元素
    public void addHash(HashSet<Person> hash) {

        Person p1 = new Person();
        Person p2 = new Person();
        Person p3 = new Person();
        Person p4 = new Person();
        Person p5 = new Person();
        Person p6 = new Person();
        Person p7 = new Person();
        p1.setAge(12);
        p1.setName("张敏");
        p2.setAge(11);
        p2.setName("吴喜爱");
        p3.setAge(14);
        p3.setName("小猫咪");
        p4.setAge(67);
        p4.setName("吴长春");
        p5.setAge(34);
        p5.setName("Tom");
        p6.setAge(67);
        p6.setName("吴长春");
        p7.setAge(34);
        p7.setName("Tom");
        hash.add(p1);
        hash.add(p2);
        hash.add(p3);
        hash.add(p4);
        hash.add(p5);
        hash.add(p6);
        hash.add(p7);
    }

    // 运用迭代器方法遍历集合
    public void iteratorPrint(HashSet<Person> hash) {
        System.out.println("迭代器方法遍历集合:");
        Iterator<Person> hashIt = hash.iterator();// 获取集合的实现类对象,病调用集合的iterator()
        while (hashIt.hasNext()) {
            Person per = hashIt.next();
            System.out.println(per.getName() + " " + per.getAge());
        }
    }

}

创建测试类:

import java.util.HashSet;

public class HashDemo {
    public static void main(String[] args) {
        HashSet<Person> hash = new HashSet<Person>();
        Way way = new Way();
        way.addHash(hash);
        way.iteratorPrint(hash);

    }
}

重写两个方法后,可以将姓名与年龄相同的对象,只保留一个,即不存储重复的元素。

LinkedHashSet集合

LinkedHashSet集合与HashSet集合的最大区别在于,LinkedHashSet集合存入和取出的顺序相同,而HashSet集合存取顺序不一定相同:

import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;

public class HashSetDemo {
    public static void main(String[] args) {
        HashSet<String> hs = new HashSet<String>();
        hs.add("qwe");
        hs.add("123qwe");
        hs.add("q23we");
        hs.add("qw1e");
        hs.add("qwe");
        Iterator<String> it = hs.iterator();
        while (it.hasNext()) {
            String s = it.next();
            System.out.println(s);
        }
        
        System.out.println("----------------------------");
        
        LinkedHashSet<String> lhs = new LinkedHashSet<String>();
        lhs.add("qwe");
        lhs.add("123qwe");
        lhs.add("q23we");
        lhs.add("qw1e");
        lhs.add("qwe");
        Iterator<String> ite = lhs.iterator();
        while (ite.hasNext()) {
            String s = ite.next();
            System.out.println(s);
        }
  }
}

HashMap集合

collection接口下的List和Set集合,存储的都是单个元素。而Map接口下的集合,存储的是键值对,键值对中,值可以相同,但是键必须不同。

1、HashMap中的常用方法:

 

import java.util.HashMap;
import java.util.Map;

public class HashMapDemo {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<String, String>();
        map.put("河南", "郑州");
        map.put("北京", "北京");
        System.out.println(map);

        System.out.println(map.get("河南"));

        System.out.println(map.remove("河南") + "已被移除");
        System.out.println(map);
        System.out.println(map.size());

    }
}

2、HashMap的遍历:

import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

public class HashMapDemo {
    public static void main(String[] args) {
        HashMap<String, String> map = new HashMap<String, String>();
        map.put("河南", "郑州");
        map.put("北京", "北京");
        Set<String> keySet = map.keySet();
        // 遍历存放所有key的Set集合
        Iterator<String> it = keySet.iterator();
        while (it.hasNext()) {
            // 得到每一个key
            String key = it.next();
            // 通过key获取对应的value
            String value = map.get(key);
            System.out.println(key + "=" + value);
        }
    }
}

原文地址:https://www.cnblogs.com/zhai1997/p/11354885.html