Java高级----List集合、Set集合、Map集合总结

一、集合的概念

1、集合概念

  (1) 集合是java中提供的一种类型 ,用于存储管理对象
  (2) 只能存对象,不能存基本数据类型,可以存基本数据类型的封装类对象

2、集合中常用的方法
方法名含义
add(E e)向列表的尾部添加指定的元素
add(int index,E element)向列表的指定位置添加指定的元素
addAll (Collection<? extends E> c)将指定 collection中的所有元素都添加到此 collection 中(可选操作)
contains(Object o)如果此 collection 包含指定的元素,则返回 true
containsAll(Collection<?> c)如果此 collection 包含指定 collection 中的所有元素,则返回 true
equals(Object o)比较此 collection 与指定对象是否相等
hashCode()返回此 collection 的哈希码值
isEmpty()判断此 collection 是否为null,为null则返回 true
size()返回此 collection 中的元素数
get()返回列表中指定位置的元素
set(int index,E element)用指定元素替换指定位置的元素
iterator()返回在此 collection 的元素上进行迭代的迭代器
remove(Object o)移除列表中第一次出现的指定元素
remove(int index)移除列表中指定位置的元素
list.indexOf(str);返回指定元素的下标值,如果集合中有多个相同的String类型与基本数据类型的封装类类型元素,只返回第一个元素的下标,其他引用类型暂时没有验证
initialCapacity()设定集合初始化容量的方法

补充
  (1) 在普通for循环中,remove方法移除元素不会发生冲突情况

public class ListDemo1 {
	public static void main(String[] args) {
		ArrayList<String> list = new ArrayList<>();
		list.add("tom");
		list.add("jom");
		list.add("jerry");
		list.add("jerry");
		
		ArrayList<String> list1 = new ArrayList<>();
		list1.add("花花");
		list1.add("豆豆");
		list.addAll(list1);
		for (int i = 0; i < list.size(); i++) {
			System.out.println(list.get(i));
		}
		System.out.println("==========");
//在普通for循环中,使用remove方法
		for (int i = 0; i < list.size(); i++) {
			if (list.contains("花花")) {
				list.remove("花花");
			}
			System.out.println(list.get(i));
		}
	}
}
//输出结果
tom
jom
jerry
jerry
花花
豆豆
==========
tom
jom
jerry
jerry
豆豆

  (2) forEach循环中使用remove方法移除元素会发生冲突报异常

//forEach遍历集合
for(String str:list) {
System.out.println(str) ;
}
// forEach的实质是一个迭代器。Iterator<E>
//当if在它内部嵌套remove的时候会对此集合进行修改,
//但是forEach不允许在执行的时候被修改,这两个线程之间会冲突,会报异常
for(String str :list) {
if(str.equals("nanyi")) {
list.remove("nanyi") ;
System.out.println(str);
}

forEach循环中正确删除元素的方式:

//forEach循环中删除元素的正确方式    建一个list集合的副本
     list = new CopyOnWriteArrayList(list);
		for (String str : list) {
			if (str.equals("fff")) {
				list.remove("fff");
			}
	} //遍历的是原先的集合,删除的是副本集合

注意:forEach循环中直接删除元素时,可能冲突报异常,也可能直接将最后一个元素删除不报异常,使用想要准确删除元素,只有上面创建副本这种方法。

二、Java中集合的分类

1、Collection接口

  (1) List接口
  (2) Set接口
  (3) Queue接口

2、Map接口

  (1) HashMap实现类
  (2) TreeMap实现类
  (3) Hashtable实现类

3、Collections工具类

三、Collection接口

1、List接口

  (1) List接口特征:
    ① 有顺序:按照下标进行存放元素
    ② 可重复:同一个对象可以多次存放在同一个List集合中
  (2) List接口的实现类:
    ① ArrayList实现类
    ② Vector实现类
    ③ LinkedList实现类

2、ArrayList实现类

  (1) ArrayList实现类特征:
    ① 实现方式: 数组实现
    ② 特点一: 增删慢,查询快
    ③ 特点二:轻量级、速度快、线程不安全
    ④ 对ArrayList数组进行扩充:ensureCapacity(size +1) ;
    ⑤ ArrayList和Vector都是基于数组实现的List类,所以ArrayList和Vector类封装了一个动态的允许再分配的Object[]数组。Arraylist和Vector对象使用initialCapacity()参数来设置数组的长度,然后当数组满了之后,其initialCapcity()会自动增加;但是如果我们要向ArrayList中添加大量元素,那么我们可以使用ecsureCapacity()方法一次性增加initialCapacity(),这样可以减少分配次数,提高性能。Object[]数组默认的长度为10.
  (2) 创建集合:

使用到了泛型
ArrayList<String> list = new ArrayList<>();
List<String> list = new ArrayList<>();

  (3) Comparable接口以及sort排序:
    ① 方法:Comparable接口中就一个compareTo();
    ② 对String字符串排序的时候,直接通过执行Collections.sort(list);就行,因为String类中已经重写了compareTo方法。

public class StringListSortDemo {
	public static void main(String[] args) {
		// 字符串类型的排序
		// 对String字符串排序的时候,直接通过执行Collections.sort(list);就行,
		// 因为String类中已经实现了Comparable接口并且重写了compareTo方法。
		List<String> list = new ArrayList<>();
		list.add("chenrui");
		list.add("peifei");
		list.add("liurui");
		list.add("yuya");
		list.add("chenjia");
		list.add("tianshui");
		list.add("meiqi");
        // 对String字符串排序的时候,直接通过执行Collections.sort(list);就行,
		Collections.sort(list);
		for (String str : list) {
			System.out.println(str);
		}
	}
}

    ③ 对非全字符串进行排序,需要实现comparable接口,然后重写compareTo();方法

package listDemo;

public class Student implements Comparable<Student> {
	private String name;
	private int age;
	private int score;

	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() {
		super();
	}

	public int getScore() {
		return score;
	}

	public void setScore(int score) {
		this.score = score;
	}

	public Student(String name, int age, int score) {
		super();
		this.name = name;
		this.age = age;
		this.score = score;
	}

	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + ", score=" + score + "]";
	}

	@Override
	public int compareTo(Student o) {
	//this.age代表集合中的第一个元素, o.age代表集合中的第二个元素
		// 根据年龄排序:升序
		// return this.age - o.age;
		// 根据年龄排序:降序
		// return o.age - this.age;
		// 根据分数排序:升序
		// return this.score - o.score;
		// 根据分数排序:降序
		// return this.score - o.score;
		// 根据姓名排序
		return this.name.compareTo(o.name);
	}

}
public class StudentListDemo {
	public static void main(String[] args) {
		Student stu1 = new Student("chenjie", 23, 100);
		Student stu2 = new Student("yuya", 45, 94);
		Student stu3 = new Student("cuiguang", 30, 94);
		Student stu4 = new Student("peifei", 13, 98);
		Student stu5 = new Student("zhuyan", 50, 96);
		Student stu6 = new Student("leima", 32, 99);
		Student stu7 = new Student("jiahui", 25, 97);
		Student stu8 = new Student("lixiao", 21, 89);
		// Student stu9 = new Student("meiqi", 22, 87);
		Student stu9 = new Student("meiqi", 21, 87);
		List<Student> list = new ArrayList<>();
		list.add(stu1);
		list.add(stu2);
		list.add(stu3);
		list.add(stu4);
		list.add(stu5);
		list.add(stu6);
		list.add(stu7);
		list.add(stu8);
		list.add(stu9);
		// 单重排序:按照姓名排序
		Collections.sort(list);
		for (Student stu : list) {
			System.out.println(stu);
		}
	}
}

  (4) Comparator多重排序:
    ① 特点:List排序的最灵活方式;
    ② 方法一、实现comparator()接口,重写compare();方法。
    ③ 方法二、创建Comparator接口匿名内部类对象,如下:

// 采用匿名内部类的方式实现多重排序
		Collections.sort(list, new Comparator<Student>() {
			@Override
			public int compare(Student o1, Student o2) {
				// 先按照年龄排序,年龄相同按照姓名排
				return o1.getAge() - o2.getAge();
			}
		});

    ④ 排序优先级:1 .先按照分数进行排序,2. 分数相同按照年龄进行排序,3 .年龄相同按照姓名进行排序:
注意:多重排序的技巧,优先级越高的放在越靠后的位置进行排序。

package listDemo;
import java.util.Comparator;
public class StudentCompare implements Comparator<Student> {
	@Override
	public int compare(Student o1, Student o2) {
		// 先按照年龄排序,年龄相同按照姓名排
		return o1.getAge() - o2.getAge();
	}
}
package listDemo;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class StudentListDemo {
	public static void main(String[] args) {
		Student stu1 = new Student("chenjie", 23, 100);
		Student stu2 = new Student("yuya", 45, 94);
		Student stu3 = new Student("cuiguang", 30, 94);
		Student stu4 = new Student("peifei", 13, 98);
		Student stu5 = new Student("zhuyan", 50, 96);
		Student stu6 = new Student("leima", 32, 99);
		Student stu7 = new Student("jiahui", 25, 97);
		Student stu8 = new Student("lixiao", 21, 89);
		// Student stu9 = new Student("meiqi", 22, 87);
		Student stu9 = new Student("meiqi", 21, 87);
		List<Student> list = new ArrayList<>();
		list.add(stu1);
		list.add(stu2);
		list.add(stu3);
		list.add(stu4);
		list.add(stu5);
		list.add(stu6);
		list.add(stu7);
		list.add(stu8);
		list.add(stu9);
		// 单重排序:按照姓名排序
		Collections.sort(list);
		for (Student stu : list) {
			System.out.println(stu);
		}

		// Compare多重排序:按照年龄排序,年龄相同的按照名字排序
		// Collections.sort(list, new StudentCompare());
		// for (Student stu : list) {
		// System.out.println(stu);
		// }

		// 采用匿名内部类的方式实现多重排序
		Collections.sort(list, new Comparator<Student>() {

			@Override
			public int compare(Student o1, Student o2) {
				// 先按照年龄排序,年龄相同按照姓名排
				return o1.getAge() - o2.getAge();
			}
		});
		for (Student stu : list) {
			System.out.println(stu);
		}

		Collections.sort(list, new Comparator<Student>() {

			@Override
			public int compare(Student o1, Student o2) {
				// 先按照年龄排序,年龄相同按照姓名排
				return o2.getScore() - o1.getScore();
			}
		});
		for (Student stu : list) {
			System.out.println(stu);
		}
	}
}
// 排序优先级,1 .先按照分数进行排序,2. 分数相同按照年龄进行排序,3 .年龄相同按照姓名进行排序
// 多重排序的技巧,优先级越高的放在越靠后的位置进行排序

    ⑤ 汉字按照汉语拼音的顺序排序:

步骤一、Comparator<Object> c = Collator.getInstance(Locale.CHINA);
步骤二、Collections.sort(list, c);

  (2)Vector实现类特征:
    ① 实现方式:数组实现;
    ② 特点一、增删慢,查询快。
    ③ 特点二、重量级、速度慢、线程安全。
  (3)LinkedList实现类特征:
    ① 实现方式:双向链表实现;
    ② 特点一、增删快,查询慢。
    ③每个元素都记录前后元素的指针,所以插入、删除数据时只是更改前后元素的指针指向即可,速度非常快。然后通过下标查询元素时需要从头开始索引,所以比较慢,但是如果查询前几个元素或后几个元素速度比较快。


注意
List其实是可以容纳不同类型的元素的。但这好像和我们平时开发的想法不太一样,在平时开发中,总是觉得List只能存储同一类型的元素,那是因为我们在定义时加上了泛型。

public static void main(String[] args) {
        List list = new ArrayList();
        list.add("1");
        list.add(1);
        System.out.println(list.toString());
    }
    ------------------------------------------
    输出:[a,1]
--加了泛型后只能存放此类型的对象
List<String> list = new ArrayList<>();
3、List去重的五种方式

  (1) 使用LinkedHashSet删除arraylist中的重复数据:
LinkedHashSet是在一个ArrayList删除重复数据的最佳方法。LinkedHashSet在内部完成两件事:

    ① 删除重复数据
    ② 保持添加到其中的数据的顺序

@Test
    void listTest1() {
        List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 2, 1, 5, 5, 1, 2, 5, 6));
        LinkedHashSet<Integer> integers1 = new LinkedHashSet<>(list);
        ArrayList<Integer> integers2 = new ArrayList<>(integers1);
        System.out.println(integers2);
    }
    ------------------------------------------
    输出:[1, 2, 3, 4, 5, 6]

  (2) 使用java8新特性stream进行List去重:要从arraylist中删除重复项,我们也可以使用java 8 stream api。使用steam的distinct()方法返回一个由不同数据组成的流,通过对象的equals()方法进行比较。收集所有区域数据List使用Collectors.toList()。

 @Test
    void listTest2() {
        List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 2, 1, 5, 5, 1, 2, 5, 6));
        List<Integer> collect = list.stream().distinct().collect(Collectors.toList());
        System.out.println(collect);
    }
    ------------------------------------------
    输出:[1, 2, 3, 4, 5, 6]

  (3) 利用HashSet不能添加重复数据的特性:由于HashSet不能保证添加顺序,所以只能作为判断条件保证顺序。

@Test
    void listTest3() {
        List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 2, 1, 5, 5, 1, 2, 5, 6));
        HashSet<Integer> set = new HashSet<>(list.size());
        ArrayList<Integer> result = new ArrayList<>(list.size());
        for (Integer a : list) {
            if (set.add(a)) {
                result.add(a);
            }
        }
        System.out.println(result);
    }
    ------------------------------------------
    输出:[1, 2, 3, 4, 5, 6]

  (4) 利用List的contains方法循环遍历,重新排序:

 @Test
    void listTest4() {
        List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 2, 1, 5, 5, 1, 2, 5, 6));
        ArrayList<Integer> result = new ArrayList<>(list.size());
        for (Integer a : list) {
            if (!result.contains(a)) {
                result.add(a);
            }
        }
        list.clear();
        list.addAll(result);
        System.out.println(list);
    }
    ------------------------------------------
    输出:[1, 2, 3, 4, 5, 6]

  (5) 双重for循环去重:

 @Test
    void listTest5() {
        List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 2, 1, 5, 5, 1, 2, 5, 6));
        for (int i = 0; i < list.size(); i++) {
            for (int j = i + 1; j < list.size(); j++) {
                if (list.get(i) == list.get(j)) {
                    list.remove(j);
                    j--;
                }
            }
        }
        System.out.println(list);
    }

四、Set接口

1、Set集合特点

  (1) 无序:存放对象的内存地址不连续,没有下标,不能使用普通的for()循环
  (2) 不可重复:同一个对象的不同引用只能存放一次
  (3) Set底层是Map,所以HashSet可以有1个null的元素,TreeSet不能有key为null的元素。

2、使用迭代器进行遍历
Iterator<String> it = strSet.iterator()
while(it.hasNext()) {
System.out.print1n(it .next());
}
3、Set接口的实现类与子接口:

  (1) Abstractset类—> HashSet实现类
  (2) SortedSet接口—> TreeSet实现类

4、Abstractset类的子类: HashSet实现类

  (1) 特点:
    ① 不能排序,能去重
    ② 移除元素与list集合一样
  (2) 排序:
    ① HashSet,是用equals()方法比较,String中已经重写了该方法,只要字符串相同,那就认为是同一个对象

//HashSet算法,是用equals( )方法比较,String中已经重写了该方法
//只要字符串相同,那就认为是同一个对象
Set<String> strSet = new HashSet<>();
strSet.add("1g");
strSet.add("ljs");
strSet.add("1g");
//迭代器,hasNext()方法判断集合是否为null
Iterator<String> it = strSet.iterator();
while (it.hasNext()) {
System.out.print1n(it.next());
}

    ② 在其他类型的类中,需要实现Compareable接口,需要重写HashCode()方法,才能达到去重的效果。
    ③HashSet的去重依据:set集合内对象的hashcode值,当hashcode值相同时,去调用对应equals方法进行比较如果比较的结果相同则不进行添加。
    ④ String,八种基本数据类型对应封装类默认重写了hashCode和equals方法,所以对应相应的类型默认去重。

5、SortedSet接口的实现类:TreeSet实现类

  (1) 特点:
    ① 存放的时候无序,但是可以进行排序,能去重
    ② //HashSet,是用equals()方法比较,String、封装类中已经重写了该方法,只要字符串相同,那就认为是同一个对象

strSet.add("lijun");
String str = new String("lijun");
atrSet.add(str);

这两个虽然是不同的创建方式,但是内容相同,所以只会添加进去一个"lijun"

  (2) 其它数据类型排序:
    ① 元素实现Comparable接口;或调用TreeSet ( Comparator<? super E> comparator ) 构造函数,传递一个Comparator对象
    ② TreeSet去重复的规则是使用Comparable接口定义的compareTo方法,或者Comparator接口中定义的compare方法
    ③ 使用以上两种方式只能对对象的单一属性进行去重或排序,如果要对TreeSet中的元素根据元素的多个属性值进行去重则可以根据对去重属性进行重写hashCode和equals方法
    ④:TreeSet的多重排序,重写CompareTo方法

@override
public int compareTo(Student o) {
return this.age-o.age ;
  }
}
this.age代表集合中第一个元素、o.age代表集合中第二个元素

五、Iterator()迭代器

1、hasNext():判断集合里面是否为空
2、next:取出集合的元素
//迭代器,hasNext( )方法判断集合是否为null
Set<String> strSet = new HashSet<>();
Iterator<String> it= strSet. iterator( );
while (it. hasNext( )) {
System. out . println(it.next( ));

六、Queue接口

1、Queue常用API

  (1) LinkedList是其实现类

2、常用方法

  (1) offer(e):添加,相当于add()方法
  (2) poll():移除队首元素,相当于remove()方法
  (3) peek(),获取队首元素,但不移除,相当于element()方法

public class QueueDemo {
	public static void main(String[] args) {
		Queue<String> queue = new LinkedList<String>();
		// add()与offer()效果一样
		queue.add("sun0");
		queue.offer("sun1");
		queue.offer("sun2");
		queue.offer("sun3");
		String str = queue.poll();
		System.out.println(str);
		System.out.println("-------------");
		for (String q : queue) {
			System.out.println(q);
		}
	}
}

输出结果为:
sun0
-------------
sun1
sun2
sun3

七、Map集合

1、特性

  (1) 存在形式:键值对 key value
  (2)其中Key值不能重复,Value的值可以重复

2、常用方法
方法名含义
put(K key, V value)向Map集合里面添加元素
get(Object key)获取key对应的value值
remove(Object key)移除此key和其对应的value值
clear()清空此集合
isEmpty()判断Map集合是否为空
size()获取集合的长度
containsKey()判断此Map集合中是否存在指定Key值
containsValue()判断此Map集合中是否存在指定Value值
entrySet()返回此映射所包含的映射关系的set视图
putAll(Map)将一个Map放到另外一个Map中
Keyset()获取所有的key,并放到collection中
3、map的遍历方式

  (1) 键遍历:keySet(),此方法获取所有的key

 Set<String> keySet = map1.keySet();
for (String str1 : keySet) {
System.out.println(str1 + "\t" + map1.get(str1));
	 }

  (2) 值遍历:values(),此方法获取所有的value

Collection<String> ct = map1.values();
for (String str2 : ct) {
System.out.println(str2);
 }

  (3) 键值遍历:entrySet()

Set<Entry<String, String>> entrys = map1.entrySet();
 for (Entry<String, String> str3 : entrys) {
	System.out.println(str3.getKey() + "\t" + str3.getValue());
		}
	}
	获取所有的key值:getKey()
    获取所有的value:getValue()
4、HashMap实现类

  (1) HashMap的特点:key与value都可以为null,但是HashMap仅可以有1个key为null的元素,TreeMap不能有key为null的元素

public class HashTableDemo {
public static void main(String[] args) [ 
Mapcstring,String> map1 = new HashMapc>( )
Map<String,String> map2 = new Hashtable<>( ) ;
map1. put(nu11,"tom") ;
map1. put("a",nu1l);
for(Entry<string, String> en:map1.entrySet()) {
System. out. print1n(en. getKey()+"\t\t"+en. getValue());
   }
}
-----------------------------
nu11  tom
a     null

  (2) map的Key值不能重复,如果重复将会覆盖原来的值

map1.put("a", "tom");
// map的Key值不能重复,如果重复将会覆盖原来的值。
map1.put("a", "tomcat");

  (3) 遍历输出的时候是按:a、b、c输出,因为是HashMap,所以回内部按照HashCode方法排序。

Map<string,String> map = new HashMap<>( );
map. put("C", "陈瑞" ) ;
map.put("b", "布袋熊");
map. put("a","阿宝");
for( Entrycstring, string> en:map.entrySet()){ 
System.out.print1n(en.getkey()+"\t"+en.getvalue());
  }
------------------------
  a 阿宝
  b 布袋熊
  C 陈瑞

  (4) jdk1.7与jdk1.8中HashMap底层原理的区别
  ① jdk8中会将链表长度达到8时,链表会转变为红黑树
  ② 新节点插入链表的顺序不相同(jdk7是插入头结 点,jdk8因为 要遍历链表把链表变为红黑树所以采用插入尾结点)
  ③ hash算法简化
  ④ resize的逻辑修改(jdk7会出现死循环,jdk8不会) (死锁场景: ht://w .importnew .com/2201 1.html)

注意:HashMap的key也是通过Hash算法 过滤重复。

5、TreeMap实现类

  (1) 排序的时候:要实现Comparable接口定义的compareTo方法,或者Comparator接口中定义的compare方法开启比较功能,排序的同时会按照排序的属性去重。
  (2) TreeMap的key是通过Comparable接口 过滤重复 排序,也可以通过Comparator接口的实现类的对象来过滤重复排序。
注意:是按照key值进行排序,不是按照value的值排序

6、Hashtable实现类

  (1) Hashtable特点:任何非null对象都可以用作键和值。

  (2) Hashtable 与 HashMap的区别:

HashMap轻量级、速度快、线程不安全允许key与value为null
Hashtable重量级、速度慢、线程安全不允许key与value为null

  (3) HashMap的初始容量为16,Hashtable初始容量为11,两者的填充因子默认都是0.75。HashMap扩容时是当前容量翻倍即:capacity2,Hashtable扩容时是容量翻倍+1即:capacity2+1。
  (4) HashMap计算hash对key的hashcode进行了二次hash,以获得更好的散列值,然后对table数组长度取模;Hashtable计算hash是直接使用key的hashcode对table数组的长度直接进行取模。
注意
    ① map集合中不能直接使用Iterator进行迭代
    ②只有实现了collection集合才有iterator方法,比如List和set接口;而Map接口不能使用iterator方法,需要现获取set视图,即Set set = map.keySet();set就可以使用了。

7、Collections工具类

  (1) 根据指定比较器产生的顺序,返回给定collection的最大元素:T max(Collection coll)
  (2) 根据指定比较器产生的顺序,返回给定collection的最大元素:T min(Collection coll)
  (3) 使用方式:Student stu = Collections.max(stuSet);
  (4) 使用默认随机源对指定列表进行置换,也就是打乱集合的顺序,相当于与洗扑克牌:shuffle(List<?> list) Collections.shuffle(list);只会打乱,不会有返回值。
  (5) List synchronizedList(List list)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值