Java集合(1)List 和Set 之ArrayList和TreeSet/HashSet 及工具类 Collections

首先,集合只能存储引用类型的对象。

集合 和 数组区别:
  1.数组 长度固定的;
    集合 长度不固定;
  2.数组 存储 基本 类型 和 引用类型;
    集合 只能存储引用类型;
  3.性能上。
    数组更好;
    集合底层数据结构复杂。

这篇文章先只说左边部分 也就是 Collection接口的List 和 Set。

上边的接口图如果觉得看的不爽,可以瞧瞧这里https://www.cnblogs.com/ysocean/p/6555373.html

Collection接口:

  存储数据可以重复并且是无序的。

Collection下 List 接口实现了 存储的数据可以重复,但是有序的

                      Set 接口则实现了存储数据的无序,但是唯一

先说List 的实现类 ArrayList

下面看关系:

public interface List<E> extends Collection<E>

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E>

public class ArrayList<E> extends AbstractList<E>

所有的集合都是这样的,Collection->List->抽象类->ArrayList(实现类)

写一个Demo吧,看一下ArrayList能用的方法。

package day0815;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.function.Predicate;

public class Demo1 {
	public static void main(String[] args) {
		//创建集合
        //这里为什么要这样写呢,当然你写ArrayList list=new ArrayList();
        //也是没关系的,说不上来为什么,可能就属于编程习惯?! 体现了多态嘛
		Collection<String> c=new ArrayList();
        //集合是否为空 空的话返回为true
		System.out.println(c.isEmpty());
        //为集合添加元素
		c.add("1");
		c.add("3");
		c.add("2");
        //增强for循环,只能对有序的,这点有序指的是有下标的,对于Set则不能用for循环遍历
		for(String a:c) {
			System.out.println(a);
		}
		System.out.println(c);
        //打印集合的长度  数组是,length  集合是size()
		System.out.println(c.size());
        //addAll()方法是向集合添加整个集合,如下 把c 加到c 里
		c.addAll(c);
		c.addAll(c);
		c.addAll(c);
        //再看看大小
		c.size();
        //移除 集合 c 中的 d元素,返回值为boolean ,有这个元素删除了 返回true,没有则返回                     false
		System.out.println(c.remove("d"));
		//在集合中删除传入集合所有元素,只要删除了一个则返回true,否则返回false(重复的元素也会删除)
//		c.removeAll(c); 
		System.out.println(c);
        //符合条件的删除,匿名内部类重写方式
		c.removeIf(new Predicate<String>() {

			@Override
			public boolean test(String t) {
				// TODO Auto-generated method stub
				if(Integer.valueOf(t)>1) {
					return true;
				}else {
					return false;
				}
			}
			
		});
        //Lambda表达式定义范围
		c.removeIf(s->s.length()>1);
        //判断集合中是否存在元素
		System.out.println(c.contains("1"));
        //判断集合是否是另一个集合的子集是的话返回true,否则false
		System.out.println(c.containsAll(c));
		//把数组转换成集合  但是这个集合不是ArrayList,不能添加,删除,一般只是遍历用
		List<String> list=Arrays.asList(new String[]{"",""});
		System.out.println(c);
        //把集合转为数组
		Object []all=c.toArray();
		String [] wtf=c.toArray(new String [c.size()]);
		for(Object a:wtf) {
			System.out.println(a);
		}
		c.clear();
	}

}
package day0815;

import java.util.ArrayList;
import java.util.List;

public class Demo2 {
	public static void main(String[] args) {
		List <String> list=new ArrayList<>();
		list.add("aa");
		list.add("bb");
		list.add("cc");
		System.out.println(list);
		list.add(1, "ff");
        //修改下标为2的元素改为 “wtf”
		list.set(2, "wtf");
		System.out.println(list);
        //取得下标为0的元素
		System.out.println(list.get(0));
        //是否存在“aa”元素,存在返回true 否则返回false
		System.out.println(list.indexOf("aa"));
        //返回最后一个“aa”的元素的开始的下标
		System.out.println(list.lastIndexOf("aa"));
        //集合截取 类比SubString
		System.out.println(list.subList(0, 2));
        //排序,传入空类型实现默认自然排序
		list.sort(null);
		System.out.println(list);
	}

}
package day0815;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.function.Consumer;

public class Demo3 {
	public static void main(String[] args) {
		List<String> list=new ArrayList<>();
		list.add("aa");
		list.add("bb");
		list.add("cc");
//		//1.基本for循环只限于List
//		for(int i=0;i<list.size();i++) {
//			System.out.println(list.get(i));
//		}
//		//2.增强for
//		for(String s:list) {
//			System.out.println(s);
//		}
//		//3.集合的方法
//		list.forEach(new Consumer<String>() {
//
//			@Override
//			public void accept(String t) {
//				// TODO Auto-generated method stub
//				System.out.println(t);
//			}
//			
//		});
        //Lambda 简化
//		list.forEach(t->System.out.println(t));
//		list.forEach(System.out::println);
        //属于集合的Iterator 迭代器
		Iterator<String> it=list.iterator();
		System.out.println(it.next());
//		while(it.hasNext()) {
//			System.out.println(it.next());
//			list.add("hello");
//		}
		ListIterator<String> li=list.listIterator();
		while(li.hasNext()) {
			System.out.println(li.next());
			li.add("Hello");
		}
//		while(li.hasPrevious()) {
//			System.out.println(li.previous());
//			li.add("Hello");
//		}
		System.out.println(list);
		//it 是个类似指针 不会返回
//		it.forEachRemaining(System.out::println);
		list.stream().forEach(System.out::println);
	}

}

工具类Collections:

package day0816;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Demo1 {
	public static void main(String[] args) {
		List<String> list=new ArrayList<>();
		//工具类
		Collections.addAll(list, "aa","bb","cc");
		System.out.println(list);
		//默认自然升序排序
		Collections.sort(list);
		System.out.println(list);
		//指定比较器
//		Collections.sort(list, (o1,o2)->o2.compareTo(o1));
//		System.out.println(list);
		//二分查找元素没有的话返回-1  有的话 返回下标  前提是升序排序的
		System.out.println(Collections.binarySearch(list, "aa"));
		//最小元素
		System.out.println(Collections.min(list));
		//最大元素
		System.out.println(Collections.max(list));
		//在集合中出现的次数
		System.out.println(Collections.frequency(list, "aa"));
		//反转集合
		Collections.reverse(list);
		System.out.println(list);
		Collections.reverse(list);
		System.out.println(list);
		//洗排 每次都不一样
		Collections.shuffle(list);
		System.out.println(list);
		//以什么填充、全部替换
		Collections.fill(list, "wtf");
		System.out.println(list);
	}

}
package day0816;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Demo2 {

	public static void main(String[] args) {
		List<String> list=new ArrayList<>();
		list.add("张三");
		list.add("李四");
		list.add("李四");
		list.add("王五");
		list.add("张三");
		Set<String> set=new HashSet<>(list);
		
		for(String t:set) {
            //是否 有重复的元素 是返回true  否则 false
			if(Collections.frequency(list,t)!=1) {
				System.out.println(t+"重复");
			}
		}
	}
}

List 的实现类还有 Vector  通过栈实现的 ,已废弃。LinkedList 呢 其实方法实现和 ArrayList差不太多,因为底层实现的原因,多了在头部和尾部插入。

总结一下:

ArrayList :按照 50 %扩容

底层数据结构 是数组:
           遍历 和 随机访问效率高。

Vector -> Stack栈
按照 100%扩容
性能低.
线程安全的。


底层数据结构  是链表。
LinkedList
      插入 和 删除 效率高。 

下面说Set 接口

Set接口实现了数据唯一存储,但是无序

HashSet:

和ArrayList一样的

public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E>

public class HashSet<E>  extends AbstractSet<E>implements Set<E>

都是 接口->抽象类->实现类

HashSet 类:
     底层数据结构是 哈希表

下面上Demo,用法其实毕竟同源(都来自Collection接口)都差不多的

package day0815;

import java.util.HashSet;
import java.util.Set;
class Empoloyee{
	int no;
	String name;
	public Empoloyee(int no, String name) {
		super();
		this.no = no;
		this.name = name;
	}
}
public class Demo7 {
	public static void main(String[] args) {
        //定义一个set集合
		Set<Empoloyee> set=new HashSet<>();
		Empoloyee zhangsan=new Empoloyee(1, "zhangsan");
		Empoloyee lsi=new Empoloyee(3, "lsi");
		Empoloyee ww=new Empoloyee(2, "ww");
        //往里存,如果你再存相同对象的你会发现存不进去的,当然了 new 一个新的另说的
		set.add(lsi);
		set.add(ww);
		set.add(zhangsan);
		
		
		
	}

}

TreeSet:
   底层数据结构 二叉树

树: 层次结构.

package day0815;

import java.util.SortedSet;
import java.util.TreeSet;

public class Demo9 {
	public static void main(String[] args) {
		//没有索引                             //这里是重写了排序方法
		SortedSet<Integer> set=new TreeSet<>((n1,n2)->n2-n1);
		set.add(1);
		set.add(3);
		set.add(2);
		System.out.println(set);
		System.out.println(set.first());
		System.out.println(set.last());
		//【起始元素,终止元素)***
        //如果改变排序方式的话,这点就会出问题
//		System.out.println(set.subSet(2,1);
	}

}
package day0815;

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

public class Demo10 {
	public static void main(String[] args) {
        //这个我觉得就是增强的迭代器
		NavigableSet<Double> set=new TreeSet<>();
		set.add(11.1);
		set.add(22.3);
		set.add(44.4);
		set.add(111.1);
		//小于等于指定参数的最大元素
		System.out.println(set.floor(23.0));
		//大于等于指定参数的最小元素
		System.out.println(set.ceiling(20.2));
		//降序的集合
		System.out.println(set.descendingSet());
		//降序的迭代器
		set.descendingIterator().forEachRemaining(System.out::println);
        //把第一个元素删除
		set.pollFirst();
		System.out.println(set);
        //把在最后一个的元素删除
		System.out.println(set.pollLast());
	}

}

下面才是最重要的,自定义HashSet的排序方法 、

Hash唯一存储原理:
   首先 调用 hashCode()算出一个 哈希地址 ,
   把 元素 存进去 ,如果 ,哈希 冲突的 ,
   hashCode()的值 一样了 ,这时  才会调用‘  
   equals()判断 两个对象是否相同 ,相同不存储,
    不同 可以存储。’

package work0815;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

class Mouse implements Comparable{
	String name;
	String favorite;
	int age;
	@Override
    //自定义hashCode的方法,让算hashCode 是通过this.name.hashCode()+this.age 去计算
	public int hashCode() {
		// TODO Auto-generated method stub
		return this.name.hashCode()+this.age;
	}
	@Override
       //自定义判断大小的方法
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		Mouse mouse=null;
		if(obj instanceof Mouse) {
			mouse=(Mouse)obj;
			
		}
		return this.name.equals(mouse.name);
	}
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return this.age+"";
	}
	public Mouse(String name, String favorite, int age) {
		super();
		this.name = name;
		this.favorite = favorite;
		this.age = age;
	}
	@Override
	public int compareTo(Object o) {
		// TODO Auto-generated method stub
		return this.age-((Mouse)o).age;
	}
	
}
public class Work2 {
	public static void main(String[] args) {
		Mouse m1=new Mouse("qwe", "看书", 2);
		Mouse m2=new Mouse("asd", "看报", 4);
		Mouse m3=new Mouse("zcx", "学习", 1);
		Set<Mouse> set=new HashSet<>();
		set.add(m1);
		set.add(m2);
		set.add(m3);
		//转为List 集合 进行排序
		List<Mouse> list=new ArrayList<>(set);
		list.sort(null);
		System.out.println(list);
		System.out.println(set);
		Mouse m4=new Mouse("qwe", "2", 2);
		set.add(m4);
		System.out.println(set);
        //这样的话 即使是新对象也是存不进去的
		set.remove(new Mouse("qwe", "睡觉", 2));
		System.out.println(set);
		
		
	}

}

如有不正,敬请指出。

猜你喜欢

转载自blog.csdn.net/smile_geek_sq/article/details/81709110