第七章 集合

1 篇文章 0 订阅
1 篇文章 0 订阅

第七章 集合

集合概念

存储一个班学员信息,假定一个班容纳20名学员 当我们需要保存一组一样(类型相同)的元素的时候,我们应该使用一个容器 来存储,数组就是这样一个容器。

数组的缺点:数组一旦定义,长度将不能再变化。 然而在我们的开发实践中,经常需要保存一些变长的数据集合,于是,我们需 要一些能够动态增长长度的容器来保存我们的数据。 而我们需要对数据的保存的逻辑可能各种各样,于是就有了各种各样的数据结构。

Java中对于各种数据结构的实现,就是我们用到的集合。

概念:Java集合是使程序能够存储和操纵元素不固定的一组数据。 所有Java集合类都位于java.uti包中。 与Java数组不同,Java集合中不能存放基本数据类型,只能存放对象的引用。

集合API

集合体系概述

Java的集合框架是由很多接口、抽象类、具体类组成的,都位于java.util包中。
在这里插入图片描述

Collection接口

Collection 接口-定义了存取一组对象的方法,其子接口Set和List分别定义

了存储方式。

Set 中的数据对象没有顺序且不可以重复。

List 中的数据对象有顺序且可以重复。

在Collection 中定义了一些集合中的共有方法:

boolean add(Object element); //将元素添加到集合中

boolean remove(Object element); //删除指定元素,成功返回true,失败返回false;

void clear(); //将集合中的元素清空

int size(); //返回集合中的元素个数

boolean isEmpty(); //判断集合是否为空,为空返回true,不为空返回false;

boolean contains(Object element); //如果集合包含指定元素,则返回true,否则返回false;

boolean retainAll(Collection c);求交集,集合数据发生变化返回true, 不变返回false。

List 接口及实现类

List继承了Collection接口,有三个实现的类 (可重复)

- ArrayList

数组列表,数据采用数组方式存储,在内存中分配连续的空间。 添加慢,查询快, 中间增删慢(后面的元素位置要发生改变),所以遍历元素和随机访问元素的效率比较高
在这里插入图片描述

ArrayList的常用方法

add(int index, E element) //将元素添加到指定位置

get(int index) //获取指定位置的元素

indexOf(Object o) //返回给定元素第一次出现的索引,如果集合没有此元素,则返回-1;

lastIndexOf(Object o) //返回给定元素最后一次出现的索引,如果集合没有此元素,则返回-1;

remove(int index) //删除并返回指定位置元素

removeRange(int fromIndex, int toIndex)// 删除指定区间的元素(子类继承使用)

set(int index, E element)//用指定元素替换索引所在位置的元素

public class ArrayListDemo {
    public static void main(String[] args){
        ArrayList<String> str=new ArrayList<>();
        str.add("f");
        str.add("q");
        str.add("w");
        str.add("z");
        str.add("x");
        str.add("j");
        str.add("n");
        str.add(4, "v");//向指定位置添加元素
        System.out.println(str);
        System.out.println(str.get(4));//取出指定位置元素
        System.out.println(str.remove(5));//删除并返回指定位置的元素
        System.out.println(str);
        str.set(3,"e");//替换指定位置的元素
        System.out.println(str);
    }
}

扩容方式:首先调用grow方法,会自动创建一个大小为10的数组,如果元素达到10个,还有元素需要存,那么该方法自动调用grow方法,会创建一个大小为以前数组的1.5倍的数组用于存储元素,下面就是源码扩容:
在这里插入图片描述

-LinkedList

以链表的方式进行存储,添加快,查询慢(必须从头/尾开始查找,直到找到),中间增删快,只需要改变后继节点位置。
在这里插入图片描述

LinkedList的常用方法

add(int index,Object element) //向指定位置添加元素

addFirist(Object element) //向集合的首位添加元素

addLast(Object element) //向集合的末尾添加元素

addLast(Object element)

get(int index) //获取指定索引的元素

removeFirst()//删除集合首位元素

removeLast() //删除集合末尾元素

remove(int index) //删除指定索引的元素

getFirst() //获取集合首位元素

getLast()//获取集合末尾元素

public class LinkedListDemo {
    public static void main(String[] args) {
        LinkedList<String> list=new LinkedList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("e");
        System.out.println(list);
        System.out.println(list.get(3));//从指定位置获取元素
        list.addFirst("X");//往首位添加元素
        list.addLast("Y");//往末尾添加元素
        System.out.println(list.removeFirst());//删除第一个元素并返回
        System.out.println(list.removeLast());//删除最后一个元素并返回
        System.out.println(list);
    }
}

扩容方式:因为LinkedList是以链表的形式存储,所以在内存中就不用创建连续地址空间,因为链表会自动寻找空间,所以扩容方式没有ArrayList那么复杂。

-Vector

数组列表,添加同步锁,线程安全的

public class VectorDemo {
    /*
    用于线程安全,底层实现和ArrayList没区别
     */
    public static void main(String[] args) {
        Vector<String> v=new Vector<>();
        v.add("a");
        v.add("b");
        v.add("c");
        v.add("d");
        v.add("e");
        System.out.println(v);
    }
}

List接口集合迭代

for循环遍历 (因为去重就需要遍历,所以这里就用该方式演示)

public class Demo2 {
    /*
    定义一个String类型的ArrayList集合,去除ArrayList中的重复元素
  
     */
    public static void main(String[] args) {
        ArrayList<String> str=new ArrayList<>();
        str.add("a");
        str.add("b");
        str.add("c");
        str.add("d");
        str.add("d");
        str.add("d");
        str.add("d");
        for (int i = 0; i < str.size(); i++) {
            for (int j = i+1; j < str.size(); j++) {
                if(str.get(i)== str.get(j)){
                    str.remove(j);
                    j--;
                }
            }
        }
        System.out.println(str);
    }
}

增强for循环的遍历

import java.util.ArrayList;

public class Demo3 {
    /*
    定义一个String类型的ArrayList集合,去除ArrayList中的重复元素

     */
    public static void main(String[] args) {
        ArrayList<String> str=new ArrayList<>();
        str.add("a");
        str.add("b");
        str.add("c");
        str.add("d");
        str.add("d");
        str.add("d");
        str.add("d");
        for(String s:str){
            System.out.println(s);
        }

    }
}

迭代器遍历(Iterator)

package com.ffyc.gather.list;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.ListIterator;

public class IteratorDemo1 {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.add("d");
        list.add("d");
        list.add("d");
        list.add("d");
        list.add("e");
        Iterator<String> it = list.iterator();
        while (it.hasNext()) {//判断是否还有下一个元素
            String str = it.next();
            // System.out.println(str);遍历
            if (str.equals("d")) {
                it.remove();
            }//删除重复项
        }
        System.out.println(list);
        LinkedList<String> list1 = new LinkedList<>();
        list1.add("a");
        list1.add("b");
        list1.add("c");
        list1.add("d");
        list1.add("d");
        list1.add("d");
        list1.add("d");
        list1.add("d");
        list1.add("f");
        ListIterator<String> it1 = list1.listIterator();//第二种迭代器从指定位置开始遍历,这里从size()即末尾往前遍历
        /*
        ListIterator<String> it1 = list1.listIterator(list1.size());
        while (it1.hasPrevious()) {
            String str1 = it1.previous();
            System.out.println(str1);
        }
        }
         */
        while (it1.hasNext()) {//这里是从头开始遍历
            String str1 = it1.next();
            System.out.println(str1);
        }
    }
}

Set 接口

Set接口继承了Collection接口。

Set中所存储的元素是不重复的,但是是无序的, Set中的元素是没有索引的

Set接口有两个实现类

HashSet

HashSet类中的元素无序且不能重复,即彼此调用equals方法比较,都返回false。

底层数据结构是哈希表+链表

哈希表依赖于哈希值存储

package com.ffyc.gather.set;

public class Car implements Comparable<Car>{

	
	 private int no;
	 private String name;
	 
	public Car(int no, String name) {
		super();
		this.no = no;
		this.name = name;
	}

	@Override
	public int compareTo(Car o) {
	 
		return this.no-o.no;
	}

	@Override
	public String toString() {
		return "Car [no=" + no + ", name=" + name + "]";
	}
	
	
	 
	 
}


package com.ffyc.gather.set;

import java.util.HashSet;

public class HashSetDemo1 {

    public static void main(String[] args) {
		 /*
		     HashSet中不能存储重复元素
		          如何判断元素是否重复
		          在add的底层方法中,每天加一个元素时,就会判断集合中是否已经包含了此元素.
		          在底层使用hashCode()和equals()方法来判断内容是否重复
		     hashCode()是Object类中的方法
		     public native int hashCode(); native修饰的方法称为本地方法,java没有实现,是调用的操作系统中的方法
		     Object类中的 hashCode()获取的对象在内存中的地址
		           其他类中重写的hashCode(),都不对象的地址,而是根据对象内容计算出来的哈希值.
		     aaaaa-->int  1234
		     abcd-->int 1234
		     equals(); 除了Object类中的equals是比较对象地址,其他类中都是比较内容是否相等,因为equls效率很低


		     hashCode();  判断时,先调用hashCode()计算哈希值,用整数哈希值来比较是否相等,这样提高了比较效率
		                                            但是此种做法不安全,因为内容不同,可能计算的哈希值相同.
		     equals();  当有哈希值相同时,再去调用equal()方法比较内容是否相等. 这样就包证了安全性.
		  */

        //如果类中Car中没有重写hashCode(),调用的是Object中,默认是对象地址,每个new出来的对象都是独一无二的
        Car s1 = new Car(101, "宝马");
        Car s2 = new Car(102, "奔驰");
        Car s3 = new Car(103, "大众");
        Car s4 = new Car(101, "宝马");
        HashSet<Car> set = new HashSet<>();
        set.add(s1);
        set.add(s2);
        set.add(s3);
        set.add(s4);
        System.out.println(set);
    }

}

TreeSet

可以给Set集合中的元素进行指定方式的排序。存储的对象必须实现Comparable接口。

TreeSet底层数据结构是二叉树(红黑树是一种自平衡的二叉树)

package com.ffyc.gather.set;



import java.util.TreeSet;

public class TreeSetDemo {

	 public static void main(String[] args) {
		/*
		     有序且不重复
		   public TreeSet() {
			    this(new TreeMap<E,Object>());
			    TreeSet (键,值)键不可重复,值可以重复
			    如果键重复,只会保留最后一次,而且最后一次的值会覆盖前面的键所对应的值

			}
		 */
		 TreeSet<String> set = new TreeSet<>();
		                 set.add("c");
		                 set.add("b");
		                 set.add("z");
		                 set.add("a");
		                 set.add("x");
		                 set.add("x");
		      System.out.println(set);
		      
		      
		      Car car1 = new Car(1,"baoma1");
		      Car car2 = new Car(2,"baoma2");
		      Car car3 = new Car(3,"baom3");
		      TreeSet<Car> carset = new TreeSet<>();
		      carset.add(car1);
		      carset.add(car3);
		      carset.add(car2);
		      System.out.println(carset);//会以键排序
	}
}

Set 接口集合迭代

遍历方式

增强for循环

package com.ffyc.gather.set;



import java.util.TreeSet;

public class TreeSetDemo {

	 public static void main(String[] args) {
		/*
		     有序且不重复
		   public TreeSet() {
			    this(new TreeMap<E,Object>());
			    TreeSet (键,值)键不可重复,值可以重复
			    如果键重复,只会保留最后一次,而且最后一次的值会覆盖前面的键所对应的值

			}
		 */
		 TreeSet<String> set = new TreeSet<>();
		                 set.add("c");
		                 set.add("b");
		                 set.add("z");
		                 set.add("a");
		                 set.add("x");
		                 set.add("x");
		
		 for(String s:set){
			 System.out.println(s);
		 }
	}
}

迭代器遍历

package com.ffyc.gather.set;



import java.util.Iterator;
import java.util.TreeSet;

public class TreeSetDemo {

	 public static void main(String[] args) {
		/*
		     有序且不重复
		   public TreeSet() {
			    this(new TreeMap<E,Object>());
			    TreeSet (键,值)键不可重复,值可以重复
			    如果键重复,只会保留最后一次,而且最后一次的值会覆盖前面的键所对应的值

			}
		 */
		 TreeSet<String> set = new TreeSet<>();
		                 set.add("c");
		                 set.add("b");
		                 set.add("z");
		                 set.add("a");
		                 set.add("x");
		                 set.add("x");
	
			 Iterator<String> it=set.iterator();
			 while (it.hasNext()){
				 System.out.println(it.next());
			 }

	}
}

Map 接口

Map接口概述

将键映射到值的对象 ,一个映射不能包含重复的键 ,每个键最多只能映射到一个值。

Mapa接口常用方法

V put(K key,V value) //将给定的键,值存储到图中

V remove(Object key) //将图中指定键删除

void clear() //将图中所有的键和值删除

boolean containsKey(Object key) //如果图中含有指定键,则返回true

boolean containsValue(Object value) //如果图中含有指定值,则返回true

boolean isEmpty() //判断图中是否为空

int size() //返回图的大小

V get(Object key) //返回指定键的值

Collection values() 将键的值取出来放到定义的图中

Set keySet()//将键取出来放到定义的set中

Set<Map.Entry<K,V>> entrySet()//将键值对取出放到set中,这是一个内部类,遍历添加到set中

HashMap

HashMap中元素的key值不能重复,排列顺序是不固定的,可以存储一个为null的键。

1)TreeMap

TreeMap中所有的元素都保持着某种固定的顺序,如果需要得到一个有序

的Map就应该使用TreeMap,key值所在类必须实现Comparable接口。

package com.ffyc.gather.map;



import java.util.Hashtable;
import java.util.TreeMap;



public class TreeMapDemo {

	
	public static void main(String[] args) {
		/*
		 TreeMap
 		此实现提供了所有可选的地图操作,并不允许null的值和null键
	   
		 */
		 TreeMap<String,String> map = new TreeMap<>();
		                   map.put("a", "aa");
		                   map.put("s", "ss");
		                   map.put("b", "bb");
		                   map.put("x", "xx");
		                   map.put("x", "aa");
		                   map.get("b");
		                   
		       System.out.println(map);
		       
		          Car car1 = new Car(1,"baoma1");
			      Car car2 = new Car(2,"baoma2");
			      Car car3 = new Car(3,"baom3");
			      TreeMap<Car,String> cmap = new TreeMap<>();
			      cmap.put(car1, "aaa");
			      cmap.put(car3, "ccc");
			      cmap.put(car2, "bbb");
			      System.out.println(cmap);
		                
	 
	}
}

2)TreeMap

适用于按自然顺序或自定义顺序遍历键(key)。

TreeMap根据key值排序,key值需要实现Comparable接口,重compareTo方法。TreeMap根据compareTo的逻辑,对 key进行排序。

键是红黑树结构,可以保证键的排序和唯一性

package com.ffyc.gather.map;

import java.util.Collection;
import java.util.HashMap;
import java.util.Set;


public class HashMapDemo {

	
	public static void main(String[] args) {
		/*
		 HashMap
		   此实现提供了所有可选的地图操作,并允许null的值和null键
		 */
		HashMap<String,String> map = new HashMap<>();
		                   map.put("a", "aa");
		                   map.put("s", "ss");
		                   map.put("b", "bb");
		                   map.put("x", "xx");
		                   map.put("x", "aa");
		                   map.put(null, "cc");
		                
		      
		   System.out.println(map.remove("a"));//删除主键为a的元素,并返回该键的值
		   //map.clear(); 删除全部元素
		     System.out.println(map.containsKey("a"));//如果此map包含指定键的映射,则返回 true
		     System.out.println(map.containsValue("aa"));//如果此map将一个或多个键映射到指定值,则返回 true
		     System.out.println(map.isEmpty());//是否为空
		     System.out.println(map.size());
		     Collection<String> c = map.values();//将键的值取出来放到定义的c中
		     Set<String> set =   map.keySet();//将键取出来放到定义的set中
		     System.out.println(map.get("b"));
		     map.replace("b", "XXXX");
		     
		  System.out.println(map);
		  System.out.println(c);
		  System.out.println(set);
	}
}

Map集合遍历

方式1:根据键找值

1)获取所有键的集合

2)遍历键的集合,获取到每一个键

3)根据键找值

方式2:根据键值对对象找键和值

1)获取所有键值对对象的集合

2)遍历键值对对象的集合,获取到每一个键值对对象

3)根据键值对对象找键和值

package com.ffyc.gather.map;

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

public class EntryDemo {
    public static void main(String[] args) {
        HashMap<String, String> map = new HashMap<>();
        map.put("111", "aaa");
        map.put("222", "bbb");
        map.put("444", "xxx");
        map.put("333", "qqq");
        map.put("666", "aaa");
        Set<Map.Entry<String, String>> mapentry = map.entrySet();
        /*双列表遍历,采用entry()方法,将Map转换为set,可以采用增强for循环遍历
        增强for循环
        //for(数据类型 变量名  :   需要循环的数据){
        循环体
        }

         */
        //  (数据类型                   变量名    : 需要循环的数据)
        for(Map.Entry<String,String> mapentry1 : mapentry){
            System.out.println(mapentry1);
        }
    }
}


HashTable

实现了同步。

不能存储为null的键

Collections类

Collections是集合类的工具类,与数组的工具类Arrays类似。

addAl l(Col lection<? super T> c, T... elements); //向指定集合添加元素 binarySearch(List<? extends Comparable<? super T>> l ist, T key) 返回指定元素在集合的位置 sort(List l ist)对集合中的元素进行排序 sort(List l ist, Comparator<? super T> c)这是对Collections.sort方法重写,可以自定义排序,也是内部类,后边会学习 swap(List<?> l ist, int i, int j)//对集合指定两个位置进行交换
copy(List<? super T> dest, List<? extends T> src) ;//对集合进行复制,注意新的集合空间必须大于等于旧的集合空间 emptyList() 返回为空的集合,不能添加数据 fill(List<? super T> l ist, T obj)//用指定的元素代替指定列表的所有元素。 max(Col lection<? extends T> col l)//根据其元素的 自然顺序返回给定集合的最大元素。 min(Col lection<? extends T> col l)//根据其元素的 自然顺序返回给定集合的最小元素。 replaceAl l(List l ist, T oldVal, T newVal)//将集合中某个值全部替换为指定值 reverse(List<?> l ist)//反转指定列表中元素的顺序。
shuffle(List<?> l ist) //使用默认的随机源随机排列指定的列表。 lection<? super T> c, T... elements); //向指定集合添加元素 binarySearch(List<? extends Comparable<? super T>> l ist, T key) 返回指定元素在集合的位置 sort(List l ist)对集合中的元素进行排序 sort(List l ist, Comparator<? super T> c)这是对Collections.sort方法重写,可以自定义排序,也是内部类,后边会学习 swap(List<?> l ist, int i, int j)//对集合指定两个位置进行交换
copy(List<? super T> dest, List<? extends T> src) ;//对集合进行复制,注意新的集合空间必须大于等于旧的集合空间 emptyList() 返回为空的集合,不能添加数据 fill(List<? super T> l ist, T obj)//用指定的元素代替指定列表的所有元素。 max(Col lection<? extends T> col l)//根据其元素的 自然顺序返回给定集合的最大元素。 min(Col lection<? extends T> col l)//根据其元素的 自然顺序返回给定集合的最小元素。 replaceAl l(List l ist, T oldVal, T newVal)//将集合中某个值全部替换为指定值 reverse(List<?> l ist)//反转指定列表中元素的顺序。
shuffle(List<?> l ist) //使用默认的随机源随机排列指定的列表。
copy(dest,src)集合复制

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值