【java基础】List,Set和Map及典型题练习

(一)基础知识
1.集合中List,Set和Map都是接口,List和Set实现了Collection接口。
List接口下的实现类:ArrayList,LinkedList和Vector
Set接口下的实现类:HashSet和TreeSet
Map接口下的实现类:HashMap,TreeMap和Hashtable
2.数组必须是相同类型的,集合可以是不同类型的组合(泛型可以限制类型–只能是引用类型)基本数据类型对应的包装类(引用类型)如下:
在这里插入图片描述
3.ArrayList,LinkedList和Vector的区别:
ArrayList:底层数据结构是数组,查询快,增删改慢,线程不安全但效率高。
LinkedList:底层数据结构是链表,查询慢,增删改快,线程不安全但效率高。
Vector:底层数据结构是数组,查询快,增删改慢,线程安全但效率低。
4.HashSet和Treeset的区别:
HashSet:底层数据结构是哈希表,元素不排序。
Treeset:底层数据结构是二叉树,元素排序。----自定义类型通过实现接口Comparable中的compareTo()方法进行比较,可以重写compareTo()方法:

@Override
public int compareTo(Object obj) {
//this在前,升序排列:
return this.%-obj.%;//数值类型
//或者:
return this.%.compareTo(obj.%);//String类型

//this在后,降序排列:
return obj.%-this.%;//数值类型
//或者:
return obj.%.compareTo(this.%);//String类型
}

5.HashMap,Hashtable和TreeMap的区别:
HashMap:线程不安全但效率高,键和值都允许有null值存在。源码中public修饰的方法都是同步的(有 synchronized关键字)。父类是Dictionary。
Hashtable:线程安全但效率低,键和值都不允许有null值存在。源码中public修饰的方法都不是同步的(没有 synchronized关键字)。父类是AbstractMap。
TreeMap:实现了排序。TreeMap中默认的对key值的排序为升序,如果要改变其排序可以自己写一个Comparator。
比如下面的例子就实现了对整型key值的降序排序:

class Com implements Comparator<Integer>{
	@Override
	public int compare(Integer o1, Integer o2) {
		return o2-o1;//降序
	}
}
public class TreeMapTest {
	public static void main(String[] args) {
		Com com=new Com();
		TreeMap<Integer,Integer> map=new TreeMap<Integer,Integer>(com);
		map.put(1,2);
		map.put(3,2);
		map.put(4,2);
		map.put(2,2);
		System.out.println(map);
	}
}

显示结果:
在这里插入图片描述

6.List,Set和Map的区别:
List:有序(进出顺序一致),可以有重复的元素。有一个泛型。add()方法添加元素。
Set:无序(进出顺序不一致),元素去重(唯一)----默认调用hashcode()和equals()方法比较是否重复(String类型已经改写过hashcode()和equals()方法,自定义类型需要自己重写hashcode()和equals()定义比较的参数)。有一个泛型。add()方法添加元素。
(补充:想要有序即进出顺序一致的话可以使用Set下的比较特殊的类
—>LinkedHashSet )
Map:无序(进出顺序不一致),键值对形式有两个泛型。put()方法添加键(key)值(value)。
(补充:想要有序即进出顺序一致的话可以使用Map下的比较特殊的类
—>LinkedHashMap )
List和Set是Collection的子接口,但Map不是。
7.Map的三种遍历方式:
(1)keySet():
例:

HashMap<String,String> map=new HashMap<String,String>();
map.put("001", "张三");
map.put("002", "李四");
Set<String> set=map.keySet();
Iterator<String> it=set.iterator();
while(it.hasNext()){
	String key=it.next();
	System.out.println(key+"----"+map.get(key));
}

(2)values():
例:

HashMap<String,String> map=new HashMap<String,String>();
map.put("001", "张三");
map.put("002", "李四");
Collection<String> c=map.values();
Iterator<String> it=c.iterator();
while(it.hasNext()){
	System.out.println(it.next());
}

(3)entrySet(),创建Entry对象:
例:

HashMap<String,String> map=new HashMap<String,String>();
map.put("001", "张三");
map.put("002", "李四");
Collection<Entry<String,String>> c=map.entrySet();
Iterator<Entry<String, String>> it=c.iterator();
while(it.hasNext()){
	Entry<String, String> entry=it.next();
	System.out.println(entry.getKey()+"----"+entry.getValue());
}

8.Collection和Collections的区别:
java.util.Collection: 是一个集合接口。它提供了对集合对象进行基本操作的通用接口方法。
java.util.Collections: 是一个包装类。它包含有各种有关集合操作的静态多态方法。此类不能实例化,就像一个工具类,服务于Java的Collection框架。
(二)练习
1.List典型题之List去重
思路一:定义另一个新集合,如果不包含旧集合的元素则加到新集合里。(自定义类型重写equals())
思路二:将List中的元素放进Set中去重后再放回List中。(自定义类型重写hashCode()和equals())

例:
(1)整型List去重后输出List:
//思路一实现如下:

public static void nonDuplicate(ArrayList<Integer> list){
        ArrayList<Integer> listNew=new ArrayList<Integer>();
        for (Integer i:list) {
            if(!listNew.contains(i)){
                listNew.add(i);
            }
        }
        System.out.println(listNew);
}

//思路二实现如下:

public static void nonDuplicate(ArrayList<Integer> list){
		HashSet<Integer> set=new HashSet<Integer>();
		set.addAll(list);
		list.clear();
		list.addAll(set);
	}

(2)学生List去重后输出List:
//思路一实现如下:
(注:需要重写equals()方法–使其比较学号,姓名和年龄,才能用contains方法比较是否重复–因为List的contains()方法默认调用实体类的equals()方法)

class Student{
	private String stuNo;
	private String stuName;
	private int age;
	public Student() {
	
	}
	public Student(String stuNo, String stuName, int age) {
		this.stuNo = stuNo;
		this.stuName = stuName;
		this.age = age;
	}
	public String getStuNo() {
		return stuNo;
	}
	public void setStuNo(String stuNo) {
		this.stuNo = stuNo;
	}
	public String getStuName() {
		return stuName;
	}
	public void setStuName(String stuName) {
		this.stuName = stuName;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
@Override
	public String toString() {
		return "Student [stuNo=" + stuNo + ", stuName=" + stuName + ", age="
				+ age + "]";
	}
	@Override
	public boolean equals(Object obj) {
       Student s = (Student) obj;
       if(s.stuNo.equals(this.stuNo) && s.stuName.equals(this.stuName) && s.age==this.age){
    	   return true;
       }
       return false;
	}
}
public class ListTest {
	public static void nonDuplicate(ArrayList<Student> list){
        ArrayList<Student> listNew=new ArrayList<Student>();
        for (int i=0;i<list.size();i++) {
            if(!listNew.contains(list.get(i))){
                listNew.add(list.get(i));
            }
        }
        System.out.println(listNew);
	}
	public static void main(String[] args) {
		ArrayList<Student> list=new ArrayList<Student>();
		Student s1=new Student("001","张三",19);
		Student s2=new Student("002","李四",20);
		Student s3=new Student("001","张三",19);
		list.add(s1);
		list.add(s2);
		list.add(s3);
		nonDuplicate(list);
	}
}

//思路二实现如下:
(注:同上需要先重写实体类学生类的equals()方法,另外在Set比较自定义类型是否相等时还要先比较hashcode是否相等,详述见下方Set去重方法)

class Student{
	private String stuNo;
	private String stuName;
	private int age;
	public Student() {
	
	}
	public Student(String stuNo, String stuName, int age) {
		this.stuNo = stuNo;
		this.stuName = stuName;
		this.age = age;
	}
	public String getStuNo() {
		return stuNo;
	}
	public void setStuNo(String stuNo) {
		this.stuNo = stuNo;
	}
	public String getStuName() {
		return stuName;
	}
	public void setStuName(String stuName) {
		this.stuName = stuName;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "Student [stuNo=" + stuNo + ", stuName=" + stuName + ", age="
				+ age + "]";
	}
	@Override
	public int hashCode() {
		return this.stuNo.hashCode()*11+this.stuName.hashCode()*13+this.age*17;
	}
	@Override
	public boolean equals(Object obj) {
       Student s = (Student) obj;
       if(s.stuNo.equals(this.stuNo) && s.stuName.equals(this.stuName) && s.age==this.age){
    	   return true;
       }
       return false;
	}
}
public class ListTest {
	public static void nonDuplicate(ArrayList<Student> list){
		HashSet<Student> set=new HashSet<Student>();
		set.addAll(list);
		list.clear();
		list.addAll(set);
		System.out.println(list);
	}
	public static void main(String[] args) {
		ArrayList<Student> list=new ArrayList<Student>();
		Student s1=new Student("001","张三",19);
		Student s2=new Student("002","李四",20);
		Student s3=new Student("001","张三",19);
		list.add(s1);
		list.add(s2);
		list.add(s3);
		nonDuplicate(list);
	}
}

2.(1)Set典型题之自定义类型Set去重
Set去重比较是否相等的原则:先hashCode()后equals()原则。
即先运行实体类的hashCode()方法来比较hascode是否相等,如果相等则直接认为元素重复,hascode不相等才会需要运行实体类的equals()方法比较是否相等。
重写hashCode()方法原则:尽量乘奇数值如11,13,17等来减少equals()运行的概率—因为先hashcode比较是否相等,不相等的话才会运行equals()方法,hashcode相等的话就不会运行equals()方法了。
(2)Set典型题之自定义类型TreeSet排序
TreeSet排序的比较原则:通过实现接口Comparable中的compareTo()方法进行比较后排序。
例:
(1)创建一个HashSet集合,在Set中增加4个工人,基本信息如下:
姓名 年龄 工资
zhang 18 3000.2
li 25 500.3
li 25 500.3
zhang 18 3000.2
要求:将三个对象去重,去重条件为:姓名,年龄,工资都一样的对象,认为“相等”,即重复了。

class Worker implements Comparable<Worker>{
	private String name;
	private int age;
	private double salary;
	public Worker() {
		
	}
	public Worker(String name, int age, double salary) {
		super();
		this.name = name;
		this.age = age;
		this.salary = salary;
	}
	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 double getSalary() {
		return salary;
	}
	public void setSalary(double salary) {
		this.salary = salary;
	}
	@Override
	public String toString() {
		return "Worker [name=" + name + ", age=" + age + ", salary=" + salary
				+ "]";
	}
	@Override
	public int hashCode() {
		return this.name.hashCode()*11+this.age*13+String.valueOf(this.salary).hashCode()*17;
	}
	@Override
	public boolean equals(Object obj) {
		if(obj instanceof Worker){
			Worker w=(Worker)obj;
			if(this.name.equals(w.name) && this.age==w.age && this.salary==w.salary){
				return true;
			}
		}
		return false;
	}
	@Override
	public int compareTo(Worker w) {
		return w.salary==this.salary?w.name.compareTo(this.name):(int)(w.salary-this.salary);
	}
	
}
public class HashSetTest {
	public static void main(String[] args) {
		Worker w1=new Worker("zhang",18,3000.2);
		Worker w2=new Worker("li",25,500.3);
		Worker w3=new Worker("zhang",18,3000.2);
		Worker w4=new Worker("li",25,500.3);
		HashSet<Worker> set=new HashSet<Worker>();
		set.add(w1);
		set.add(w2);
		set.add(w3);
		set.add(w4);
		Iterator<Worker> it=set.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
	}

}

(2)创建一个TreeSet集合,在Set中增加4个工人,基本信息如下:
姓名 年龄 工资
Zhang1 18 3000.2
li 1 28 500.3
li2 66 500.3
zhang2 45 3000.2
要求:按照工资降序排序,工资一样的,按照姓名降序排序。

class Worker implements Comparable<Worker>{
	private String name;
	private int age;
	private double salary;
	public Worker() {
		
	}
	public Worker(String name, int age, double salary) {
		super();
		this.name = name;
		this.age = age;
		this.salary = salary;
	}
	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 double getSalary() {
		return salary;
	}
	public void setSalary(double salary) {
		this.salary = salary;
	}
	@Override
	public String toString() {
		return "Worker [name=" + name + ", age=" + age + ", salary=" + salary
				+ "]";
	}
	@Override
	public int hashCode() {
		return this.name.hashCode()*11+this.age*13+String.valueOf(this.salary).hashCode()*17;
	}
	@Override
	public boolean equals(Object obj) {
		if(obj instanceof Worker){
			Worker w=(Worker)obj;
			if(this.name.equals(w.name) && this.age==w.age && this.salary==w.salary){
				return true;
			}
		}
		return false;
	}
	@Override
	public int compareTo(Worker w) {
		return w.salary==this.salary?w.name.compareTo(this.name):(int)(w.salary-this.salary);
	}
	
}
public class TreeSetTest {
	public static void main(String[] args) {
		Worker w1=new Worker("zhang1",18,3000.2);
		Worker w2=new Worker("li1",25,500.3);
		Worker w3=new Worker("zhang2",45,3000.2);
		Worker w4=new Worker("li2",66,500.3);
		TreeSet<Worker> set=new TreeSet<Worker>();
		set.add(w1);
		set.add(w2);
		set.add(w3);
		set.add(w4);
		Iterator<Worker> it=set.iterator();
		while(it.hasNext()){
			System.out.println(it.next());
		}
	}
}

3.(1)Map典型题之统计数组中每个数字出现的次数
思路:Map中的key值放数组中的数字,value值放这个数字出现的次数。
并利用Map具有的特性:如果key值相同,那么后放入的键值对中的value值会冲刷掉之前放的值。

(2)Map典型题之利用TreeMap对key值,value值排序
思路:自定义一个类实现Comparator并重写它的compare()方法,单对key值排序可以直接传key值,如果要实现对value值排序需要传Entry类对象。
例:
(1)现有一个数组int[] a=new int[]{1,2,3,22,3,4,2,4};请统计出每个数字出现的次数,输出格式如下:数字1出现1次,数字2出现2次,数字……
//思路:数组元素放在map的key值里,出现的次数放在value值里。

public class HashMapTest {
	public static void main(String[] args) {
		int[] a=new int[]{1,2,3,22,3,4,2,4};
		HashMap<Integer,Integer> map=new HashMap<Integer,Integer>();
		for(int i=0;i<a.length;i++){
			if(map.containsKey(a[i])){
				map.put(a[i],map.get(a[i])+1);
			}else{
				map.put(a[i],1);
			}
		}
		Set<Integer> set=map.keySet();
		Iterator<Integer> it=set.iterator();
		while(it.hasNext()){
			Integer key=it.next();
			System.out.println(key+"出现了"+map.get(key)+"次");
		}
	}
}

(2)写一个方法,传入一个int数组,返回一个结果,结果内包含每个数字出现的次数,并按照数字进行降序排序
例如:int[] numbers=new int[]{49,8,49,59,1,30,1,49};
统计完结果为:数字59 次数2,数字49 次数3,数字30 次数1,数字8次数1

class Com implements Comparator<Integer>{
	@Override
	public int compare(Integer o1, Integer o2) {
		return o2-o1;
	}
}
public class TreeMapTest {
	public static void sort(int[] numbers){
		Com com=new Com();
		TreeMap<Integer,Integer> map=new TreeMap<Integer,Integer>(com);
		for(int i=0;i<numbers.length;i++){
			if(map.containsKey(numbers[i])){
				map.put(numbers[i],map.get(numbers[i])+1);
			}else{
				map.put(numbers[i],1);
			}
		}
		Set<Integer> set=map.keySet();
		Iterator<Integer> it=set.iterator();
		while(it.hasNext()){
			int key=it.next();
			System.out.println("数字"+key+" 次数"+map.get(key)+",");
		}
	}
	public static void main(String[] args) {
		int[] numbers=new int[]{49,8,49,59,1,30,1,49};
		sort(numbers);	
	}
}

(3)写一个方法,传入一个int数组,返回一个结果,结果内包含每个数字出现的次数,并按照出现的次数降序,如果次数相同则按照数字进行降序排序
例如:int[] numbers=new int[]{49,8,49,59,1,30,1,49};
统计完结果为:数字49 次数3,数字59 次数2,数字30 次数1,数字8次数1

class Comp1 implements Comparator<Map.Entry<Integer,Integer>>{
	@Override
	public int compare(Entry<Integer, Integer> o1, Entry<Integer, Integer> o2) {
		// value降序,value一样按照  key降序
		return o2.getValue()-o1.getValue()==0?o2.getKey()-o1.getKey():o2.getValue()-o1.getValue();
	}
	
}
public class TreeMapTest {
	public static void sort(int[] numbers){
		Comp1 comp1=new Comp1();
		TreeMap<Integer,Integer> map=new TreeMap<Integer,Integer>();
		for(int i=0;i<numbers.length;i++){
			if(map.containsKey(numbers[i])){
				map.put(numbers[i],map.get(numbers[i])+1);
			}else{
				map.put(numbers[i],1);
			}
		}
		List<Map.Entry<Integer, Integer>> list=new ArrayList<>(map.entrySet());
		Collections.sort(list,comp1);
		for(int i=0;i<list.size();i++){
			System.out.println("数字"+list.get(i).getKey()+"出现了"+list.get(i).getValue()+"次");
		}	
	}
	public static void main(String[] args) {
		int[] numbers=new int[]{49,8,49,59,1,30,1,49};
		sort(numbers);
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值