List、Set、Map集合基础概念以及常用方法

List:

List集合类常用的有:ArrayList(连续空间)、LinkedList(不连续空间)

特点:

1)实现List接口的集合类中的元素是有序的,且允许重复

2) List集合中的元素都对应一个整数型的序号记载其在集合中的位置,可以根据序号存取集合中的元素。

List接口特有方法:

List集合因为支持索引,所以多了很多索引操作的独特api,其他Collection的功能List也都继承了。

ArrayList:

ArrayList底层是基于数组实现的:根据索引定位元素快,增删需要做元素的移位操作。 第一次创建集合并添加第一个元素的时候,在底层创建一个默认长度为10的数组。

ArrayList是一个可以动态修改的数组,没有固定长度,可以灵活的进行增删改。

ArrayList 继承了 AbstractList ,并实现了 List 接口。

ArrayList特征:查询效率, 查询某个下标的元素, 只需要计算出下标的地址码,不要一个一个找, 插入,删除效率, 需要移位

ArrayList常用方法:

添加:add()

删除:remove()

访问:get()

修改:set()

判断:contains()

计算大小:size()

判断数组为空:isEmpty()

查找指定元素下标:indexOf()

package cn.sz.gl.test01;

import java.util.ArrayList;
import java.util.List;

public class Test02 {

	public static void main(String[] args) {
		ArrayList list = new ArrayList();
		
		list.add("zhangsan");
		list.add("lisi");
		list.add("wangwu");
			
		System.out.println("集合长度:"+list.size());
		//list.clear();//清空集合中的所有数据
		System.out.println("调用clear方法后,集合长度:"+list.size());
		
		boolean flag = list.contains("lisis");//判断集合中是否包含指定的数据
		System.out.println("判断集合中是否包含指定的数据:"+flag);
		
		int index = list.indexOf("wangwu");//用来获取元素保存在list集合中的索引号
		System.out.println("获取指定数据的索引号:"+index);
		
		boolean isempty = list.isEmpty();
		System.out.println("判断集合是否有元素:"+isempty);
		
		int index2 = list.lastIndexOf("wangwu");
		System.out.println("从后往前查找指定的元素,并返回元素的索引号:"+index2);
		
		Object obj = list.remove(2);//用来删除指定位置的元素, 并返回该已经删除的元素
		System.out.println("删除第2位的数据后,集合的长度:"+list.size());
		System.out.println("删除的元素是:"+obj);
		
		boolean isRemove = list.remove("lisi");//删除指定的元素,并返回是否删除成功
		System.out.println("删除lisi后,集合的长度:"+list.size());
		System.out.println("删除lisi后,返回值是:"+isRemove);
		
		list.set(0, "zhangsans");//修改指定位置的元素
		System.out.println("集合长度:"+list.size());
		System.out.println("set之后,元素内容:"+list.get(0));
		
		
		
		list.add("111");
		list.add("222");
		list.add("333");
		list.add("xxxx");
		list.add("yyyy");
		list.add("zzz");
		List list2 = list.subList(2, 5);//获取原list集合中的某一部分元素(获取子集),这里包含第2个,但不包含第5个
		for (int i = 0; i < list2.size(); i++) {
			System.out.print(list2.get(i)+"\t");
		}
		System.out.println();
		System.out.println("***************************************");
		
		Object os [] = list.toArray();//把集合转变为一个数组
		for (int i = 0; i < os.length; i++) {
			System.out.print(os[i]+",");
		}
		
	}
}

LinkedList:

底层数据结构是双链表查询慢,首尾操作的速度是极快的,所以多了很多首尾操作的特有API。

LinkeList特有方法:

 其他方法与上述ArrayList常用方法相同,根据需求来使用两种数组即可

ArrayList和LinkedList的区别:

 

Set:

Set集合的特点:

  • 无序:存取顺序不一致

  • 不重复:可以去除重复

  • 无索引:没有带索引的方法,所以不能使用普通for循环遍历,也不能通过索引来获取元素。

Set集合类常用的有:

        HashSet:散列存放(重点)

        TreeSet:有序存放(重点)

        LinkedHashSet: 有次序

HashSet:

特点:去重、无序,唯一

HashSet 实现了 Set 接口。

HashSet 中的元素实际上是对象,一些常见的基本类型可以使用它的包装类。

HashSet基于HashMap实现,默认构造函数是构建一个初始容量为16负载因子为0.75 的HashMap。

hashCode()和equals():

怎么判断元素是否存在:

  1. 调用元素的hashCode() 方法, 如果不一样, 说明这两个对象不是同一个

  2. 如果一样, 调用equlas()方法, 如果返回true, 说明这两个对象是同一个

返回false: 说明这两个对象不是同一个

如果是自定义的类类型, 需要这个类重写hashCode()与equlas()方法

因为hashCode()和equals()方法的返回值共同决定了两个对象是否相等,所以覆写着两个方法时一般要保证两个方法的返回值保证兼容。

重写hashCode()和equals()方法的基本规则:

1、 如果两个对象通过equals()方法比较时返回true,则两个对象的hashCode()方法返回值应该也相等。

2、 对象中用作equals()比较标准的成员变量(属性),也应该参与到hashCode的计算。

LinkedSet:

特点:去重、有序、唯一

根据元素的hashCode值来决定元素的存储位置,但是它同时使用链表维护元素的次序

LinkedHashSet集合特点:

底层是一个哈希表(数组+链表/红黑树)+链表,多了一条链表(记录元素的存储顺序),保证元素有序

遍历的时候,LinkedHashSet将会以元素的添加顺序访问集合的元素

LinkedHashSet的方法与它父类HashSet方法是一样的

TreeSet:

TreeSet使用红黑树结构对加入的元素进行排序存放,所以放入TreeSet中元素必须是可“排序”的。

TreeSet可是采用两种方法实现排序:自然排序定制排序。默认情况,TreeSet采用自然排序。

TreeSet调用调用集合元素的CompareTo()方法,根据该方法的返回值来比较元素之间的大小,然后进行“升序”排列,这种排序方式我们称之为自然排列。

注意:如果想采用自然排序,则要存储的对象所属类必须实现Comparable 接口。该接口只有一个方法public int compareTo(Object obj),必须实现该方法。

compareTo方法的实现规则:

        返回 0,表示 this == obj。//则不会添加新对象(this)

        返回正数,表示 this> obj //添加到原来对象(obj)的右边

        返回负数,表示 this < obj // 添加到原来对的左边

实现例:

public class Student implements Comparable<Student> {
    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) {
        this.age = age;
    }
    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Student() {
    }
    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("Student").append('[')
                .append("name=")
                .append(name)
                .append(",age=")
                .append(age)
                .append(']');
        return sb.toString();
    }

    @Override
    public int compareTo(Student o) {
        //根据年龄升序排序
        int rs =   this.age - o.age;
        if(rs == 0 ){
            if(o == this){
                return 0;
            }else{
                return -1;
            }
        }
        return rs;
    }
}
public class TreeSetDemo {

    public static void main(String[] args) {
        TreeSet treeSet = new TreeSet();

       treeSet.add(new Student("张三",21));
        treeSet.add(new Student("李四",18));
        treeSet.add(new Student("王五",20));
        treeSet.add(new Student("李琦",19));
        System.out.println(treeSet);

    }
}

定制排序:

使用Comparable接口定义排序顺序有局限性:实现此接口的类只能按compareTo()定义的这一种方式排序。

如果需要更加灵活地排序,我们可以自定义(Comparator)比较器,在创建TreeSet集合对象时把我们自定义的比较器传入,则可以TreeSet会按照我们的比较器中定义的规则进行排序。

自定义比较器类,需要实现Comparator接口。Comparator接口只有一个抽象方法需要实现:public int compare(Object a, Object b);

判断规则:

        返回 0,表示a == b

        返回正数,表示b > b

        返回负数,表示a < b

创建TreeSet集合对象时,把自定义比较器对象传入即可,TreeSet会自动按照比较器中的规则进行排序。

实现例:

public class TreeSetDemo {
    public static void main(String[] args) {
        TreeSet treeSet = new TreeSet(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                Student stu1 = (Student)o1;
                Student stu2 = (Student)o2;
                //按照年龄的降序排序
                return  stu2.getAge() - stu1.getAge() ;
            }
        });
       treeSet.add(new Student("张三",21));
        treeSet.add(new Student("李四",18));
        treeSet.add(new Student("王五",20));
        treeSet.add(new Student("李琦",19));
        System.out.println(treeSet);
    }
}

Map:

        Map集合: 存储的key/value键值对

        Map: 映射(一一对应), key与value的映射, 一个key对应一个value

Map集合特征:

        1) 通过键-值(key-value)对的形式来存储数据

        2) Map的实现:HashMap(使用频率最高的),TreeMap,HashTable

        3) Map中,key可以为任意类型,但这里建议使用String,value也可以是任意类型

        4) Map里面多个value可以是不同类型

        5) Map里面key是可以重复的,当key重复时,后存入的数据会覆盖前面的数据

        6) Map里面,value可以重复.

        7) Map里面的key可以为null,但是只能有一个,多个的时候,后面的会覆盖前面的

        8) Map中value可以是null,多个value可以同时为null。

        9) Map中的key在底层可以理解为是一个Set

Map常用方法:

  • put(key,value)

    如果key不存在,执行添加操作

    如果key存在, 执行修改value操作

  • remove(key) 根据key删除key/value对

  • get(key) 根据key获取value

  • containsKey(key) 判断key是否存在, 如果存在,返回true, 不存在: false

  • containsValue(value) 判断value是否存在, 如果存在,返回true, 不存在: false

  • clear() 清空

  • size() 元素个数

  • isEmpty() 判断Map是否是空, true: 是空 , false: 不是空,有元素

  • 循环遍历Map

    1. entrySet()

    2. keySet()

    3. values()

构造方法:

 

负载系数: 0.75

ArrayList扩容: 数组长度比size小的时候, 才扩容

Map扩容: 扩容阈值 = 容量 * 负载系统 = 16*0.75 = 12

map的key,value对: 在map中使用一个对象保存, 对象是Node类, Node又是Entry的实现类

 

HashMap底层原理:

        HashMap底层数据结构: 数组+ 链表/红黑树(jdk1.8以及之后)

        jdk1.8之前底层数据结构:数组+ 链表

存储原理:

  1. 它的底层会调用K的hashCode()方法得出hash值。

  2. 通过哈希表函数/哈希算法,将hash值转换成数组的下标.

  3. 下标位置上如果没有任何元素,就新创建一个Node节点,并添加到这个位置上。如果说下标对应的位置上有链表。此时,就会拿着k和链表上每个节点的k进行equal。如果所有的equals方法返回都是false,那么这个新的节点将被添加到链表的末尾(尾插入)。如其中有一个equals返回了true,那么这个节点的value将会被覆盖。

Map使用代码示例:

Map接口常用的实现子类有java.util.HashMap和java.util.Hashtable

import java.util.*;

public class HashMapDemo {
	public static void main(String[] args) {
		//1.创建HashMap对象,用来存放国家英文简写与国家中文全称
		Map map  = new HashMap();
		//2.往HashMap添加元素(键-值对)
		map.put("CN", "中华人民共和国");
		map.put("RU", "俄罗斯联邦");
		map.put("US", "美利坚合众国");
		map.put("FR", "法兰西共和国");
		//3.获取key为"CN"对应的值
		String value = (String) map.get("CN");
		System.out.println(value);
		//4.向上集合元素的个数
		System.out.println("map集合共有:"+map.size()+"个元素");
		//5.判断是否存在"FR"的键
		System.out.println("map集合中是否包含FR吗?"+map.containsKey("FR"));
		//6 获取Map中键的集合和值得集合
		System.out.println("map中key的集合:"+map.keySet());
		System.out.println("map中value的集合:"+map.values());
	}
}

HashMap的遍历:

目的:遍历出map集合中所有数据

方法一:

        1.通过keySet()方法,找到所有key的集合,返回类型是一个Set;

        2.通过Iterator迭代器,迭代出Set中的每一个key;

        3.通过get(key)方法,根据上一步得到的key,来获取对应的value

Set keys = map.keySet();
Iterator iterator = keys.iterator();
while(iterator.hasNext()){
Object key = iterator.next();
Object val = map.get(key);
}

 

方法二:

        1.通过values()方法,获取map集合中所有的value的集合.返回值类型为Collection(该接口是List和Set的父接口,该类型下有Iiterator迭代器,可以用来迭代)

        2.通过Iterator迭代器,迭代出所有的value

Collection values = map.values();
Iterator iterator = values.iterator();
while(iterator.hasNext()){
Object value = iterator.next();
}

方法三:

        1.通过entrySet()方法,得到一个Entry对象的集合,这里用Set来装载.

        2.通过Set中的迭代器,迭代出每一个Entry对象.

        3.针对每一个Entry对象,通过getKey()和getValue()方法,来分别获取到对应的key和value

Set entrySet = map.entrySet();
Iterator iterator = entrySet.iterator();
while(iterator.hasNext()){
Map.Entry entry = (Map.Entry)iterator.next();
Object key = entry.getKey();
Object value = entry.getValue();
}

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值