Java集合的用法及特点

单列List集合:

  • A:集合的由来

  • 数组长度是固定,当添加的元素超过了数组的长度时需要对数组重新定义,太麻烦,java内部给我们提供了集合类,能存储任意对象,长度是可以改变的,随着元素的增加而增加,随着元素的减少而减少

  • B:数组和集合的区别

  • 区别1 :

      * 数组既可以存储基本数据类型,又可以存储引用数据类型,基本数据类型存储的是值,引用数据类型存储的是地址值
    
      * 集合只能存储引用数据类型(对象)集合中也可以存储基本数据类型,但是在存储的时候会自动装箱变成对象
    
  • 区别2:

      * 数组长度是固定的,不能自动增长
    
      * 集合的长度的是可变的,可以根据元素的增加而增长
    
  • C:数组和集合什么时候用

  • 1,如果元素个数是固定的推荐用数组

  • 2,如果元素个数不是固定的推荐用集合

Collection集合的基本功能用法

public static void main(String[] args) {
    Collection c = new ArrayList();    //创建集合对象
    c.add("a");       //添加元素,返回值为boolean
    c.remove("a");    //删除元素,返回值为boolean
    c.clear();        //清空集合,无返回值
    boolean pd = c.contains("a");   //判断是否包含元素,包含则返回true
    boolean pd = c.isEmpty();        //判断集合是否为空,为空返回true
    int num = c.size();            //获取集合中元素的个数,返回值为int
}

Collection集合的带All功能用法

public static void main(String[] args) {
    Collection c1 = new ArrayList();
    c1.add("a");
    c1.add("b");
    c1.add("c");
    c1.add("d");

    Collection c2 = new ArrayList();
    c2.addAll(c1);      //c1全部赋值给c2集合
    c1.removeAll(c2);   //删除c1内与c2交集的部分,返回值为boolean
    boolean b = c1.containsAll(c2);//判断调用的集合是否包含传入的集合
    boolean c = c1.retainAll(c2);//取c1和c2的交集,存入c1
    //如果调用的集合改变就返回true,注意:如果c2无值则c1也将变为无值
    System.out.println(c1);
    System.out.println(c2);
}

集合的遍历之集合转数组遍历

public static void main(String[] args) {
    Collection c = new ArrayList();    //创建集合对象
    c.add("a");       
    c.add("b");    
    c.add(new Student("王欢", 28));    //创建对象存入数组
   
    Object[] arr = c.toArray();     //将集合转换为数组
    for (int i = 0; i < arr.length; i++) {
        System.out.println(arr[i]);
    }
    
}

集合的遍历之迭代器遍历

public static void main(String[] args) {
    Collection c1 = new ArrayList();
    c1.add("a");
    c1.add("b");
    c1.add("c");
    c1.add("d");

    Iterator it = c1.iterator();//获取c1集合的迭代器
    while (it.hasNext()) {  //判断集合中是否有元素
        System.out.println(it.next());  //获取元素
    }

    Collection c2 = new ArrayList();
    c2.add(new Student("张三", 23));
    c2.add(new Student("李四", 18));

    Iterator it2 = c2.iterator();//获取c2集合的迭代器
    while (it2.hasNext()) {
        Student s = (Student)it2.next();    //向下转型
        System.out.println(s.getName());
    }

}

List集合的特有功能

public static void main(String[] args) {
    List c1 = new ArrayList();
    c1.add("a");
    c1.add("b");
    c1.add("c");
    c1.add("d");

    c1.add(1, "e");//指定索引位置添加元素
    Object obj = c1.remove(1);//通过索引删除元素并返回删除的元素
    Object obj2 = c1.get(0);    //通过索引获取指定元素
    c1.set(0, "z");         //将指定位置的元素修改
    System.out.println(obj2);
    System.out.println(c1);

}

List集合特有迭代器
该迭代器可以在遍历的同时向集合内添加元素

public static void main(String[] args) {
    List c1 = new ArrayList();
    c1.add("a");
    c1.add("b");
    c1.add("nan");
    c1.add("c");
    c1.add("d");

    ListIterator it = c1.listIterator();//List集合特有迭代器
    while (it.hasNext()) {
        String str = (String) it.next();
        if ("nan".equals(str)) {    //当集合中存在nan时则添加元素
            it.add("zzzzzzz");      //通过迭代器添加元素
        }
    }
    System.out.println(c1);

}

Vector的特有功能概述和测试【注意:Vector已被完全替代,请勿再使用】

public static void main(String[] args) {
    Vector v = new Vector();
    v.addElement("a");
    v.addElement("b");
    v.addElement("c");
    v.addElement("d");

    Enumeration en = v.elements();//获取枚举
    while (en.hasMoreElements()) {//判断集合中是否有元素
        System.out.println(en.nextElement());//获取集合中的元素
    }
}

List的三个子类的特点

ArrayList:

底层数据结构是数组,查询快,增删慢。

线程不安全,效率高。

Vector:

底层数据结构是数组,查询快,增删慢。

线程安全,效率低。

Vector相对ArrayList查询慢(线程安全的)

Vector相对LinkedList增删慢(数组结构)

LinkedList:

底层数据结构是链表,查询慢,增删快。

线程不安全,效率高。

Vector和ArrayList的区别

Vector是线程安全的,效率低

ArrayList是线程不安全的,效率高

共同点:都是数组实现的

ArrayList和LinkedList的区别

ArrayList底层是数组结果,查询和修改快

LinkedList底层是链表结构的,增和删比较快,查询和修改比较慢

共同点:都是线程不安全的

注意:线程不安全可以通过工具类改为安全的

如何选择:

查询多用ArrayList

增删多用LinkedList

如果都多ArrayList

案例:ArrayList去除集合中字符串的重复值

public class CeShi {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add("a");
        list.add("a");
        list.add("b");
        list.add("b");

        ArrayList abc = JiHeFF(list);
        System.out.println(abc);
    }

    public static ArrayList JiHeFF(ArrayList list) {
        ArrayList newList = new ArrayList();    //创建一个新集合
        Iterator it = list.iterator();          //获取迭代器

        while (it.hasNext()) {        //判断老集合中是否有元素,遍历老集合
            Object obj = it.next();  //将每一个元素临时记录住
            if (!newList.contains(obj)) {   //如果新集合中不包含该元素
                newList.add(obj);       //将该元素添加到新集合中
            }
        }
        return newList;     //将新集合返回
    }
}

案例:ArrayList去除集合重复自定义对象元素

注意:需要重写类的equals()方法

public class CeShi {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add(new Student("张三", 23));
        list.add(new Student("张三", 23));
        list.add(new Student("李四", 23));
        list.add(new Student("李四", 23));
        list.add(new Student("李四", 23));

        ArrayList newList = JiHeFF(list);
        System.out.println(newList);
    }

    public static ArrayList JiHeFF(ArrayList list) {
        ArrayList newList = new ArrayList();    //创建一个新集合
        Iterator it = list.iterator();          //获取迭代器

        while (it.hasNext()) {        //判断老集合中是否有元素,遍历老集合
            Object obj = it.next();  //将每一个元素临时记录住
            if (!newList.contains(obj)) {   //如果新集合中不包含该元素
                newList.add(obj);       //将该元素添加到新集合中
            }
        }
        return newList;     //将新集合返回
    }
}

//重写Student类的equals()方法,可以通过IDEA快速生成
@Override
public boolean equals(Object o) {
    Student s = (Student) o;
    return this.name.equals(s.name) && this.age == s.age;
}

案例:ArrayList通过迭代器获取自定义对象指定属性值

public static void main(String[] args) {
	ArrayList<Person> list = new ArrayList<Person>();
	list.add(new Person("张三", 23));
	list.add(new Person("李四", 24));
		
	Iterator<Person> it = list.iterator();    //获取迭代器
	while(it.hasNext()) {
	    //System.out.println(it.next().getName() + "..." + it.next().getAge());//next方法只能调用一次,如果调用多次会将指针向后移动多次
	    Person p = it.next();    //声明对象并将数据存入			
	    System.out.println(p.getName() + "..." + p.getAge());    //打印所需要的属性
	}
}

LinkedList的特有功能

public static void main(String[] args) {
		LinkedList list = new LinkedList();
		list.addFirst("a");	//往头添加元素
		list.addFirst("b");
		list.addFirst("c");
		list.addFirst("d");
		list.addLast("e");	//往尾添加元素
		
		//System.out.println(list.getFirst());//获取第一个
		//System.out.println(list.getLast());//获取最后一个
		//System.out.println(list.removeFirst());//删除第一个
		//System.out.println(list.removeLast());//删除最后一个
		
		System.out.println(list.get(1));//获取索引位置的元素,其实并不是靠索引,因为是链表结构,靠的是挨个查询
		System.out.println(list);
	}

增强for的功能概述和测试(foreach)

  • A:增强for概述

    • 简化数组和Collection集合的遍历
  • B:格式:

    for(元素数据类型 变量 : 数组或者Collection集合) {

    使用变量即可,该变量就是元素

    }

  • C:案例演示

    • 数组,集合存储元素用增强for遍历
  • D:好处

    • 简化遍历

增强for循环底层依赖的是迭代器(Iterator)

//增强for功能演示
public class CeShi {
    public static void main(String[] args) {
        ArrayList<Student> list1 = new ArrayList<>();
        list1.add(new Student("张三", 23));
        list1.add(new Student("张三", 23));
        list1.add(new Student("李四", 23));
        list1.add(new Student("李四", 23));
        list1.add(new Student("李四", 23));
        for (Student i : list1) {
            Student s1 = i;
            System.out.println(i.getName());
        }
        System.out.println("==============================");
        int[] arr = {11, 22, 33, 44, 55};
        for (int i : arr) {
            System.out.println(i);
        }
    }
}

集合元素的三种删除方式测试

  • 普通for循环,可以删除,但是索引要–

  • 迭代器,可以删除,但是必须使用迭代器自身的remove方法,否则会出现并发修改异常

  • 增强for循环不能删除

public static void main(String[] args) {
	ArrayList<String> list = new ArrayList<>();
	list.add("a");
	list.add("b");
	list.add("b");
	list.add("c");
	list.add("d");
		
	//1,普通for循环删除,索引要--
	/*for(int i = 0; i < list.size(); i++) {
		if("b".equals(list.get(i))) {
			list.remove(i--);							//通过索引删除元素
		}
	}*/
		
	//2,迭代器删除
	/*Iterator<String> it = list.iterator();
	while(it.hasNext()) {
		if("b".equals(it.next())) {
			//list.remove("b");							//不能用集合的删除方法,因为迭代过程中如果集合修改会出现并发修改异常
			it.remove();
		}
	}*/
		
	/*for(Iterator<String> it2 = list.iterator(); it2.hasNext();) {
		if("b".equals(it2.next())) {
			//list.remove("b");							//不能用集合的删除方法,因为迭代过程中如果集合修改会出现并发修改异常
			it2.remove();
		}
	}*/
	//3,增强for循环,增强for循环不能删除,只能遍历
	for (String string : list) {
		if("b".equals(string)) {
			list.remove("b");
		}
	}
	System.out.println(list);
}

单列Set集合:

//Set集合,无索引,不可以重复,无序(存取不一致)
//注意:存储类对象则需要修改类对象的equals和hashCode方法,否则可以存储重复对象
//定义HashSet
HashSet<Student> hs = new HashSet<>();
hs.add(new Student("张三", 23));

//定义LinkedHashSet,底层是链表实现的,是set集合中唯一一个能保证怎么存就怎么取的集合对象
LinkedHashSet<String> lhs = new LinkedHashSet<>();
lhs.add("a");

//定义TreeSet,用来对象元素进行排序,同样他也可以保证元素的唯一
TreeSet<Integer> ts = new TreeSet<>();
ts.add(3);

双列Map集合:

Map接口和Collection接口的不同

  • Map是双列的,Collection是单列的

  • Map的键唯一,Collection的子体系Set是唯一的

  • Map集合的数据结构值针对键有效,跟值无关;Collection集合的数据结构是针对元素有效

A:Map集合的功能概述

  • a:添加功能

  • V put(K key,V value):添加元素。

  • 如果键是第一次存储,就直接存储元素,返回null

  • 如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值

  • b:删除功能

  • void clear():移除所有的键值对元素

  • V remove(Object key):根据键删除键值对元素,并把值返回

  • c:判断功能

  • boolean containsKey(Object key):判断集合是否包含指定的键

  • boolean containsValue(Object value):判断集合是否包含指定的值

  • boolean isEmpty():判断集合是否为空

  • d:获取功能

  • Set<Map.Entry<K,V>> entrySet():

  • V get(Object key):根据键获取值

  • Set keySet():获取集合中所有键的集合

  • Collection values():获取集合中所有值的集合

  • e:长度功能

  • int size():返回集合中的键值对的个数

Map<String, Integer> map = new HashMap<>();
Integer i1 = map.put("张三", 23);//添加
Integer value = map.remove("张三");	//根据键删除元素,返回键对应的值
System.out.println(map.containsKey("张三"));		//判断是否包含传入的键
System.out.println(map.containsValue(100));		//判断是否包含传入的值

第一种迭代方式

public static void main(String[] args) {
    HashMap<String, Integer> map = new HashMap<>();
    map.put("张三", 23);
    map.put("李四", 24);
    map.put("王五", 25);
    map.put("赵六", 26);

    Integer i = map.get("张三");   //根据键获取值

    //获取所有的键
    Set<String> keySet = map.keySet();  //获取所有键的集合
    Iterator<String> it = keySet.iterator();//获取迭代器
    while (it.hasNext()) {
        String key = it.next(); //获取每一个键
        Integer value = map.get(key);//根据键获取值
        System.out.println(key + "=" + value);
    }
    System.out.println("=======================================");
    //使用增强for循环遍历
    for (String key : map.keySet()) {            //map.keySet()是所有键的集合
        System.out.println(key + "=" + map.get(key));
    }
}

第二种迭代方式

/**
	 * Map集合的第二种迭代,根据键值对对象,获取键和值
	 *  A:键值对对象找键和值思路:
		* 获取所有键值对对象的集合
		* 遍历键值对对象的集合,获取到每一个键值对对象
		* 根据键值对对象找键和值
	 */
	public static void main(String[] args) {
		Map<String, Integer> map = new HashMap<>();
		map.put("张三", 23);
		map.put("李四", 24);
		map.put("王五", 25);
		map.put("赵六", 26);
		
		//Map.Entry说明Entry是Map的内部接口,将键和值封装成了Entry对象,并存储在Set集合中
		/*Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
		//获取每一个对象
		Iterator<Map.Entry<String, Integer>> it = entrySet.iterator();
		while(it.hasNext()) {
			//获取每一个Entry对象
			Map.Entry<String, Integer> en = it.next();	//父类引用指向子类对象
			//Entry<String, Integer> en = it.next();	//直接获取的是子类对象
			String key = en.getKey();					//根据键值对对象获取键
			Integer value = en.getValue();				//根据键值对对象获取值
			System.out.println(key + "=" + value);
		}*/
		
		for(Entry<String, Integer> en : map.entrySet()) {
			System.out.println(en.getKey() + "=" + en.getValue());
		}
	}

案例:用HashMap统计字符串中每个字符出现的次数

public class CeShi {
    public static void main(String[] args) {
        //1,定义一个需要被统计字符的字符串
        String s = "abbccddddddcccbbaa";
        //2,将字符串转换为字符数组
        char[] arr = s.toCharArray();
        //3,定义双列集合,存储字符串中字符以及字符出现的次数
        HashMap<Character, Integer> hm = new HashMap<>();
        //4,遍历字符数组获取每一个字符,并将字符存储在双列集合中
        for (char c : arr) {
            //5,存储过程中要做判断,如果集合中不包含这个键,就将该字符当作键,值为1存储,如果集合中包含这个键,就将值加1存储
            /*if (!hm.containsKey(c)) {//如果不包含这个键
                hm.put(c, 1);
            } else {
                hm.put(c, hm.get(c) + 1);
            } */
            hm.put(c, !hm.containsKey(c) ? 1 : hm.get(c) + 1);
        }
        //6,打印双列集合获取字符出现的次数
        for (Character key : hm.keySet()) {             //hm.keySet()代表所有键的集合
            System.out.println(key + "=" + hm.get(key));//hm.get(key)根据键获取值
        }
    }
}

集合总结:

Collection(单列集合)

List(存取有序,有索引,可以重复)

    ArrayList

        底层是数组实现的,线程不安全,查找和修改快,增和删比较慢

      LinkedList

           底层是链表实现的,线程不安全,增和删比较快,查找和修改比较慢

    Vector

           底层是数组实现的,线程安全的,无论增删改查都慢


        * 如果查找和修改多,用ArrayList

        * 如果增和删多,用LinkedList

        * 如果都多,用ArrayList

Set(存取无序,无索引,不可以重复)

    HashSet

        底层是哈希算法实现

        LinkedHashSet

            底层是链表实现,但是也是可以保证元素唯一,和HashSet原理一样

    TreeSet

            底层是二叉树算法实现

       *一般在开发的时候不需要对存储的元素排序,所以在开发的时候大多用HashSet,HashSet的效率比较高

       * TreeSet在面试的时候比较多,问你有几种排序方式,和几种排序方式的区别

Map(双列集合)

HashMap

      底层是哈希算法,针对键

    LinkedHashMap

            底层是链表,针对键

TreeMap

      底层是二叉树算法,针对键

  *开发中用HashMap比较多
  • 10
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值