java集合框架笔记(三)之set集合

一、HashSet原理
    * 我们使用Set集合都是需要去掉重复元素的, 如果在存储的时候逐个equals()比较, 效率较低,哈希算法提高了去重复的效率, 降低了使用equals()方法的次数
    * 当HashSet调用add()方法存储对象的时候, 先调用对象的hashCode()方法得到一个哈希值, 然后在集合中查找是否有哈希值相同的对象
        * 如果没有哈希值相同的对象就直接存入集合
        * 如果有哈希值相同的对象, 就和哈希值相同的对象逐个进行equals()比较,比较结果为false就存入, true则不存

二、将自定义类的对象存入HashSet去重复
    * 类中必须重写hashCode()和equals()方法
    * hashCode(): 属性相同的对象返回值必须相同, 属性不同的返回值尽量不同(提高效率)
    * equals(): 属性相同返回true, 属性不同返回false,返回false的时候存储

三、linkedHashSet的特点:底层是链表实现的,set集合中唯一一个能保证怎么存就怎么取的集合对象,即有序存储,但也是不允许重复。

四、TreeSet集合是用来排序的,同时它能够保证数据不重复。

1.特点
    * TreeSet是用来排序的, 可以指定一个顺序, 对象存入之后会按照指定的顺序排列
2.使用方式
    * a.自然顺序(Comparable)
        * TreeSet类的add()方法中会把存入的对象提升为Comparable类型
        * 调用对象的compareTo()方法和集合中的对象比较
        * 根据compareTo()方法返回的结果进行存储
    * b.比较器顺序(Comparator)
        * 创建TreeSet的时候可以制定 一个Comparator
        * 如果传入了Comparator的子类对象, 那么TreeSet就会按照比较器中的顺序排序
        * add()方法内部会自动调用Comparator接口中compare()方法排序
        * 调用的对象是compare方法的第一个参数,集合中的对象是compare方法的第二个参数

public class sdad {

	public static void main(String[] args) {
		Comparator C = new CompareByLen();
		TreeSet<Person> tSet = new TreeSet<>(C);
		tSet.add(new Person(24,"谢晓峰"));
		tSet.add(new Person(13,"丁鹏"));
		tSet.add(new Person(36,"李寻欢"));
		tSet.add(new Person(13,"柳若松"));
		tSet.add(new Person(45,"叶开"));
    
		System.out.println(tSet);
	}
   
}
class CompareByLen implements Comparator<String>{

	/*String o1即调用的对象,是compare方法的第一个参数
	 * 集合中的对象是compare方法的第二个参数String o2*/
	@Override
	public int compare(String o1, String o2) {
		
		return 0;
	}
	
}


    * c.两种方式的区别
        * TreeSet构造函数什么都不传, 默认按照类中Comparable的顺序(没有就报错ClassCastException)
        * TreeSet如果传入Comparator, 就优先按照Comparator

在一个集合中存储了无序并且重复的字符串,定义一个方法,让其有序(字典顺序),而且还不能去除重复

			public static void main(String[] args) {
				ArrayList<String> list = new ArrayList<>();
				list.add("ccc");
				list.add("ccc");
				list.add("aaa");
				list.add("aaa");
				list.add("bbb");
				list.add("ddd");
				list.add("ddd");
				
				sort(list);
				System.out.println(list);
			}
			
			/*
			 * 对集合中的元素排序,并保留重复
			 * 1,void
			 * 2,List<String> list
			 */
			public static void sort(List<String> list) {
				TreeSet<String> ts = new TreeSet<>(new Comparator<String>() {		//定义比较器(new Comparator(){}是Comparator的子类对象)
		
					@Override
					public int compare(String s1, String s2) {						//重写compare方法
						int num = s1.compareTo(s2);									//比较内容
						return num == 0 ? 1 : num;									//如果内容一样返回一个不为0的数字即可
					}
				});
				
				ts.addAll(list);													//将list集合中的所有元素添加到ts中
				list.clear();														//清空list
				list.addAll(ts);													//将ts中排序并保留重复的结果在添加到list中
			}

从键盘接收一个字符串, 程序对其中所有字符进行排序,例如键盘输入: helloitcast程序打印:acehillostt

public static void main(String[] args) {
		Scanner scanner = new Scanner(System.in);
		System.out.println("请输入一个字符串");
		String line = scanner.nextLine();
		char[] brr = line.toCharArray();
		TreeSet<Character> treeSet = new TreeSet<>(new Comparator<Character>() {

			@Override
			public int compare(Character o1, Character o2) {
				//int num = o1-o2;
                int num = o1.compareTo(o2);
				return num==0? 1:num;
			}
		});
		for(char ch :brr) {
			treeSet.add(ch);
		}
		System.out.println(treeSet);
		for(char p:treeSet) {
			System.out.println(p);
		}

	}

1.List
    * a.普通for循环, 使用get()逐个获取
    * b.调用iterator()方法得到Iterator, 使用hasNext()和next()方法
    * c.增强for循环, 只要可以使用Iterator的类都可以用
    * d.Vector集合可以使用Enumeration的hasMoreElements()和nextElement()方法
2.Set
    * a.调用iterator()方法得到Iterator, 使用hasNext()和next()方法
    * b.增强for循环, 只要可以使用Iterator的类都可以用
3.普通for循环,迭代器,增强for循环是否可以在遍历的过程中删除 

根据源码可以知道HashSet依赖Hash算法实现

但凡hashset和hashmap存储自定义对象,要想判别自定义对象是否相同,都要重写hashcode方法和equal方法。因为不重写hashcode的方法,相同的属性值算出的hashcode的值是不一样的,那么就不会调用equal方法来比较,那么就会丢失hashset的不重复元素存储的特性。

猜你喜欢

转载自blog.csdn.net/rngweskt/article/details/82924741