List方法及去重,泛型(方法,类,接口),泛型通配符,迭代器,可变参数,set,map,Collections工具类,Comparator

List接口的链接列表实现

public void addFirst(E e)将指定元素插入此列表的开头

public void addLast(E e)将指定元素添加到此列表的结尾

public E removeFirst()移除并返回此列表的第一个元素

public E removeLast()移除并返回此列表的最后一个元素

public E getFirst()获取本列表的第一个元素

public E getLast()获取本列表的最后一个元素

 

 

LinkedList也可以存储字符串和自定义对象

 

 

使用ArrayList去除掉集合中字符串中的重复值

1️⃣新建一个集合list2,遍历list,如果list2中没有正在遍历的值,就将他插入list2,最后用迭代器对list2进行遍历

	private static void removeAgain(ArrayList list) {
		ArrayList list2 = new ArrayList();
		for(int i=0;i<list.size();i++){
			Object object = list.get(i);
			if(!list2.contains(object)){
				list2.add(object);
			}
		}
		Iterator iterator = list2.iterator();
		while(iterator.hasNext()){
			Object next = iterator.next();
			System.out.println(next);
		}
	}

2️⃣遍历这个数组,拿前面的数值和后面的数值作比较,一旦发现值相等,就将后面的删除,删除之后索引变量需要-1(ArrayList基于数组,索引发生改变)

	private static void removeAgain2(ArrayList list) {
		// TODO Auto-generated method stub
		for(int i=0;i<list.size();i++){
			for(int j=i+1;j<list.size();j++){
				if(list.get(i).equals(list.get(j))){
					list.remove(j);
					j--;
				}
			}
		}
		Iterator iterator = list.iterator();
		while(iterator.hasNext()){
			Object next = iterator.next();
			System.out.println(next);
		}
	}

 

 

 

 

 

使用LinkedList去重自定义对象

新建一个List2,遍历list,如果list2没有contains这个元素,就将它插入到list2中。

	private static void removeAgain(LinkedList list) {
		// TODO Auto-generated method stub
		LinkedList list2 = new LinkedList();
		for(int i=0;i<list.size();i++){
			Object object = list.get(i);
			if(list2.contains(object)){
				list2.add(object);
			}
		}
		showList(list2);
	}

 

 

 

 

 

泛型:为了避免类型强转发生错误,泛型左边和右边类型一致,新特性右边可以根据左边推测类型

泛型的好处:

1.提高了安全性

2.省去了类型强转可能发生的错误

3.将运行时期的错误提前到了编译时期

 

泛型只存在于编译时期,编译之后就不存在了。

 

 

在类上面自定义泛型:

public class Demo5 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		MyArrayList<String> list = new MyArrayList<>();
		list.add("姚作鹏最帅");
		String string = list.get(0);
		System.out.println(string);
	}

}

// 泛型定义在类上面,如果创建类的时候不指定确定的类型,那么默认的就是Object类型,如果指明了明确的类型,那么这个泛型在整个类就是这个指定的类型
class MyArrayList<T> {
	Object[] arr = new Object[10];

	public boolean add(T e) {
		// 遍历数组看哪个元素是空,是的话就添加值
		for (int i = 0; i < arr.length; i++) {
			Object value = arr[i];
			break;
		}
		return true;
	}

	public T get(int index) {
		return (T) arr[index];
	}
	@Override
	public String toString() {
		String result = "[";
		for (int i = 0; i < arr.length; i++) {
			Object value = arr[i];
			if (value != null) {
				result += value + " ";
			}
		}
		result = result.trim();
		result += "]";
		return result;
	}
}

 

 

 

在方法上面自定义泛型:

public static void main(String[] args) {
		// TODO Auto-generated method stub
		Object obj="哈哈";
		String s=change(obj);
		String s2=(String) obj;
		Object obj2=123;
		Integer i=change(obj2);
		Integer i2=(Integer) obj2;
	}
//	用于类型强转的泛型方法
	public static<T> T change(Object obj){
		return (T) obj;
	}

 

自定义泛型在类和方法上的区别:

 

自定义泛型在方法上是为了类型的强转,作用域是整个方法,

自定义泛型在类上作用域是在整个类内部。

 

 

带泛型的接口的子类:

如果不指定接口的泛型,那么子类也需要泛型下去,而且名字要一模一样都为<T>或者<E>

指定父接口的泛型,此时可以定义自己的泛型,也可以不定义自己的泛型

接口代码

 

public interface GenerInter<T> {
	T show();
}

实现接口代码

public class GenerDemo<T> implements GenerInter<T> {

	@Override
	public T show() {
		// TODO Auto-generated method stub
		return null;
	}

}

 

 

 

 

泛型通配符

? 代表任何类型,包括Object类型

?extend E 代表E本身或者E的子类                 向下限定通配符

?super  E 代表E本身或者E的父类向上限定通配符

 

 

 

ArrayList<Animal> list = new ArrayList<Dog>();
			ArrayList<?> list2 =new ArrayList<Dog>();
			ArrayList<? extends Animal> list3 =new ArrayList<Dog>();
			ArrayList<?super Dog> list4 =new ArrayList<Animal>();


Animal是Dog的父类,也无法直接添加泛型,。只能使用通配泛型

 

 

使用向下限定通配符,因为不确定是哪个子类,所以无法添加值,但是可以取值

ArrayList<? extends Animal> list3 =new ArrayList<Dog>();
			ArrayList<? extends Animal> list4 =new ArrayList<Cat>();
			ArrayList<? extends Animal> list5 =new ArrayList<Dog>();
public static void test(Collection<? extends Animal> list){
		Iterator<? extends Animal> iterator = list.iterator();
		Animal next = iterator.next();
	}

 

 

向上限定通配符既可以添加值,也可以取值

 

 

增强for循环Foreach

 

for (要遍历的数据类型  要遍历的变量名字 : 要遍历的数组或者集合) {

对遍历的值进行操作的语句

}

 

 

 

ArrayList<String> list = new ArrayList<>();
		list.add("1.夏红");
		list.add("2.阿翔");
		list.add("3.炸天");
		list.add("4.腰子");
		System.out.println(list);
		for (int i = 0; i < list.size(); i++) {
			System.out.print(list.get(i) + " ");
		}
		System.out.println();
		Iterator<String> iterator = list.iterator();
		while (iterator.hasNext()) {
			System.out.print(iterator.next() + " ");
		}
		System.out.println();
		for (String string : list) {
			System.out.print(string);
		}
		System.out.println();
	}

四种遍历方式。其中Foreach内部运行是迭代器。。

 

迭代器在进行迭代元素的时候不能够直接使用集合修改元素


数组一般为int value:arr 输出value

集合一般为String string:list    输出string

 

可变参数:当不知道方法的参数定义几个的时候,使用可变的参数

修饰符 返回值 方法名(数据类型...变量名){

方法体;

}

可变参数本质上是一个数组。

如果参数列表有多个参数时且存在可变参数时,无论数据类型。可变参数永远放在最后面。

public static void main(String[] args) {
		test(1,2,3,4,5,"李白");
	}

	private static void test(int...arr,String a) {
		// TODO Auto-generated method stub
		
	}

这样是错误的。

 

 

public static<T> List<T>asList(T...a)将一个数组转化为集合

Integer[] arr={1,2,3,4};
		List<Integer> asList = Arrays.asList(arr);

集合只能存储引用类型数据,只能存储基本数据类型的包装类。

 

 

Object[] toArray() 返回按适当顺序包含列表元素的数组从第一个到最后一个

Object[] array = asList.toArray();

 

 

Set集合:内部不能有重复的值

 

HashSet:存入的顺序和取出的顺序并不能保持一致。所以需要Linked

HashSet:是哈希表结构,内部依靠元素对象的hashCode和equals方法去重的,首先会判断两个对象hash值是否相同,相同再调用equals进行判断。

所以需要重写Person类中的hashCode方法和equals方法

 

 

LinkedHashSet:使用链表和哈希表

它是用链表保证元素的存入顺序和取出顺序一致。由哈希表保证元素的唯一性。

HashSet和LinkedHashSet的区别就是有序和无序

 

使用LinkedHashSet写一个取10个0-20随机数的小程序

public static void main(String[] args) {
		LinkedHashSet<Integer> set = new LinkedHashSet<Integer>();
		Random r = new Random();
		while (set.size() < 10) {
			int number = r.nextInt(20) + 1;
			set.add(number);
		}
		Iterator<Integer> iterator = set.iterator();
		while (iterator.hasNext()) {
			System.out.print(iterator.next() + "  ");
		}
	}

 

 

 

Map<K,V>。以键值对的方式存储:将键映射到值得对象,一个映射不能包含重复的键,每个键最多只能映射到一个值。

 

Map集合和Collection集合异同:

Map集合是双列的,Collection集合是单列的

Map集合存储的是以键值对的方式:key=value

Map可以有重复的值,不能存在重复的键

Map集合通过哈希表的结构保证键的唯一

 

Map集合是接口,里面的方法不能直接使用,所以使用它的子类HashMap,基于哈希表的Map接口实现,允许使用null值和null键(除了非同步和允许使用null外,HashMap和HashTable大致相同),此类不保证映射的顺序

 

                map.put(110, "警电话");
		map.put(120, "急救电话");
		map.put(119, "火警电话");
		map.put(1123, "警电话");
{1123=警电话, 119=火警电话, 120=急救电话, 110=警电话}

可以多个键指定同一个值。

                map.put(110, "警电话");
		map.put(120, "急救电话");
		map.put(119, "火警电话");
		map.put(119, "警电话");
{119=警电话, 120=急救电话, 110=警电话}

同一个键指向多个值,会被覆盖
 

 

 

 

 

HashMap方法

v put(K key,V value) 将指定的值和此映射中的指定键关联,返回的是以前和key关联的值

v remove(Object key) 移除此键对应的值,返回的是移除的值

void clear() 清空map集合

boolean containsKey(Object Key) 判断是否包含指定的键

boolean containsValue(Object Value) 判断是否包含指定的值

boolean isEmpty() 判断集合是否为空

int size() 返回Map集合中键值对的个数

 

 

 

Map集合的两种遍历方式

V get<Object key> 指定键所映射的值,如果此键不包含映射关系,返回null

Set<K> keySet() 获取键集

Collection<V> values() 获取值集

Set<Map.Entry<K,V> entrySet()> 获取键值对映射关系集

 

第一种遍历集合方式

获取所有的键,然后遍历所有的键,通过键取值

HashMap<Integer, String> map = new HashMap<Integer, String>();
		map.put(110, "警电话");
		map.put(120, "急救电话");
		map.put(119, "火警电话");
		Collection<Integer> keys = map.keySet();
		for (Integer key : keys) {
			String value = map.get(key);
			System.out.println(key+"="+value);
		}
	

 

第二种遍历方式

获取键值对对象集合,然后遍历键值对集合,通过键值对对象获取键和值

for (Map.Entry<Integer, String> entry : map.entrySet()) {
			System.out.println(entry.getKey()+"="+entry.getValue());
		}

 

 

 

HashMap类存储几种不同类型键和值案例

HashMap<String,String>

HashMap<String,Person>

HashMap<Person,String>

 

HashMap<String, Person> map = new HashMap<>();
		map.put("number 1", new Person("张三", 18, '男'));
		map.put("number 2", new Person("张四", 18, '男'));
		map.put("number 3", new Person("张五", 18, '男'));
		map.put("number 4", new Person("张六", 18, '男'));
		for (Map.Entry<String, Person> entry : map.entrySet()) {
			System.out.println(entry.getKey() + "=" + entry.getValue());
		}

 

 

 

 

Map集合嵌套List集合

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		HashMap<String, ArrayList<String>> map = new HashMap<String, ArrayList<String>>();
		ArrayList<String> list = new ArrayList<>();
		list.add("吕布");
		list.add("赵云");
		map.put("三国演义", list);
		ArrayList<String> list2 = new ArrayList<>();
		list2.add("孙悟空");
		list2.add("猪八戒");
		map.put("西游记", list2);
		ArrayList<String> list3 = new ArrayList<>();
		list3.add("令狐冲");
		list3.add("林平之");
		map.put("笑傲江湖", list3);
		for (Map.Entry<String, ArrayList<String>> entry : map.entrySet()) {
			String key = entry.getKey();
			System.out.println(key);
			ArrayList<String> value = entry.getValue();
//			遍历ArrayList集合
			for (String data : value) {
				System.out.println("\t"+data);
			}
		}
	}

实现思路:先遍历出所有list,在list里面遍历元素

 

 

Map嵌套Map,实现层层加密,三层联动等

三层密码map(map(map))

private static void test() {
		// 1.创建这个锦囊
		HashMap<Integer, String> map = new HashMap<Integer, String>();
		map.put(110, "让孙夫人摆平东吴的追兵,她是孙权妹妹,东吴将领惧她三分");
		// 2.创建第二层防护
		HashMap<Integer, HashMap<Integer, String>> map2 = new HashMap<Integer, HashMap<Integer, String>>();
		map2.put(120, map);
		// 3.创建第三层防护
		HashMap<Integer, HashMap<Integer, HashMap<Integer, String>>> map3 = new HashMap<Integer, HashMap<Integer, HashMap<Integer, String>>>();
		map3.put(119, map2);

		// 4.拆解锦囊
		Scanner sc = new Scanner(System.in);

		while (true) {
			System.out.println("请输入最外层的密码:");
			int pwd = sc.nextInt();
			HashMap<Integer, HashMap<Integer, String>> map4 = map3.get(pwd);
			if (null != map4) {// 说明密码正确,获取成功
				//解开第二层的防护
				while(true){
					System.out.println("请输入第二层的密码:");
					int pwd2 = sc.nextInt();
					HashMap<Integer,String> map5 = map4.get(pwd2);
					if(map5!=null){
						//拆开最后一层防护
						while(true){
							System.out.println("请输入最后一层的密码:");
							int pwd3 = sc.nextInt();
							String result = map5.get(pwd3);
							if(null!=result){
								System.out.println(result);
								//如果代码进入了这里,说明锦囊以及被打开了,直接结束while循环
								break;
							}
							//如果代码走到这里,说明最后一层防护没有被解开
							System.out.println("最后一层密码输出错误,请重新输出");
						}
						
						
						//如果代码进入了这里,说明第二层防护解开了,那么就结束这个while循环
						break;
					}
					System.out.println("第二层密码输出错误,请重新输出");
				}
				
				//进来了就说明密码是正确的,就可以结束这个while循环
				break;
			}
			System.out.println("最外层密码输出错误,请重新输出");
		}
	}

 

三级联动map(map(list))

	private static void test2() {
		/*
		 *  ["东城区", "西城区", "崇文区", "宣武区", "朝阳区", "丰台区", "石景山区", "海淀区", "门头沟区", "房山区", "通州区", "顺义区", "昌平区", "大兴区", "怀柔区", "平谷区", "密云县", "延庆县", "延庆镇"]);  
			dsy.add("0_0", ["北京市"]); 
		 */
		HashMap<String, ArrayList<String>> map = new HashMap<String,ArrayList<String>>();
		ArrayList<String> list = new ArrayList<String>();
		list.add("东城区");
		list.add("西城区");
		//。。。
		map.put("北京市", list);
//		map.put("北京市", "西城区");
//		map.put("北京市", "崇文区");
//		map.put("北京市", "宣武区");
//		map.put("北京市", "丰台区");
//		map.put("北京市", "石景山区");
		HashMap<String, ArrayList<String>> map2 = new HashMap<String,ArrayList<String>>();
		ArrayList<String> list2 = new ArrayList<String>();
		list2.add("瑶海区");
		list2.add("包河区");
		map2.put("合肥市", list2);
		ArrayList<String> list3 = new ArrayList<String>();
		list2.add("金安区");
		list2.add("叶集区");
		map2.put("六安市", list3);
		HashMap<String, HashMap<String, ArrayList<String>>> map3 = new HashMap<String,HashMap<String, ArrayList<String>>>();
		map3.put("北京省", map);
		map3.put("安徽省", map2);
	}

 

List嵌套Map

private static void test() {
		ArrayList<LinkedHashMap<String, String>> list = new ArrayList<LinkedHashMap<String, String>>();
		LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
		map.put("周瑜", "小乔");
		map.put("吕布", "貂蝉");
		list.add(map);

		LinkedHashMap<String, String> map2 = new LinkedHashMap<String, String>();
		map2.put("郭靖", "黄蓉");
		map2.put("杨过", "小龙女");
		list.add(map2);

		LinkedHashMap<String, String> map3 = new LinkedHashMap<String, String>();
		map3.put("令狐冲", "任盈盈");
		map3.put("林平之", "岳灵珊");
		list.add(map3);

		// 遍历
		for (LinkedHashMap<String, String> map4 : list) {
			// 遍历map4
			for (Map.Entry<String, String> entry : map4.entrySet()) {
				System.out.println(entry.getKey() + "---" + entry.getValue());
			}
			System.out.println();// 输出一个Map集合后,需要换一行
		}
	}

 

 

 

Collections类概述和成员方法:等同于Arrays,是对集合进行操作的工具类

成员方法:

public static <T> void sort(List<T> list) 对元素进行升序排序

public static <T> int binarySearch(List<?>list,T key)查找指定key在指定list集合中的位置索引,list集合必须是有序的

public static <T> T max(Collection<?> coll) 获取一个集合中最大的值

public static void reverse(List<?>  list) 将集合中的元素反转。本身升序,反转就成了降序。二分法只有在升序的情况下才可以用

public static void shuffle(List<?> list) 将集合中的元素随即打乱(模仿斗地主发牌)

 

 

斗地主发牌系统(Collections类成员方法的实战)

public static void main(String[] args) {
		// 1.创建存放牌的容器,小王14,大王15
		// 2.将所有的牌都放在容器里面
		ArrayList<Integer> list = new ArrayList<Integer>();
		for (int i = 1; i <= 4; i++) {
			for (int j = 1; j <= 13; j++) {
				list.add(j);
			}
		}
		list.add(14);
		list.add(15);
		// 3.打乱容器里的牌
		Collections.shuffle(list);
		// 4.将牌分配给四个人%4=(0-3)
		ArrayList<Integer> list2 = new ArrayList<>();
		ArrayList<Integer> list3 = new ArrayList<>();
		ArrayList<Integer> list4 = new ArrayList<>();
		ArrayList<Integer> list5 = new ArrayList<>();
		for (int i = 0; i < list.size(); i++) {
			switch (i % 4) {
			case 0:
				list2.add(list.get(i));
				break;
			case 1:
				list3.add(list.get(i));
				break;
			case 2:
				list4.add(list.get(i));
				break;
			case 3:
				list5.add(list.get(i));
				break;
			}
		}
		// 5.将每个人获取的牌都排好序
		Collections.sort(list2);
		Collections.sort(list3);
		Collections.sort(list4);
		Collections.sort(list5);
		// 6.将每个人的牌展示出来,展示的时候不能全是数字,要有JKL,小王,大王。
		show(list2);
		System.out.println();
		show(list3);
		System.out.println();
		show(list4);
		System.out.println();
		show(list5);
	}

	private static void show(ArrayList<Integer> list) {
		for (int i = 0; i < list.size(); i++) {
			Integer value = list.get(i);
			switch (value) {
			case 11:
				System.out.print("J ");
				break;
			case 12:
				System.out.print("K ");
				break;
			case 13:
				System.out.print("Q ");
				break;
			case 14:
				System.out.print("小王  ");
				break;
			case 15:
				System.out.print("大王  ");
				break;
			default:
				System.out.print(value + " ");
				break;
			}
		}
	}

 

 

 

 

public static <T> void sort(List<T> list,Comparator<? super T> c)根据指定比较器产生的顺序对指定列表进行排序

比较器接口一般是用于给java提供好的类进行排序的

对String和Integer进行排序

public static void main(String[] args) {
	ArrayList<String> list = new ArrayList<String>();
	list.add("yz");
	list.add("gh");
	list.add("ef");
	list.add("cd");
	list.add("ab");
	System.out.println(list);
	Collections.shuffle(list);
	System.out.println(list);
	Collections.sort(list, new Comparator<String>() {

		@Override
		public int compare(String o1, String o2) {
			// TODO Auto-generated method stub
			//o1和o2比较是升序
			//o2和o1比较是降序
			return o1.compareTo(o2);
		}
	});
	System.out.println(list);
}

Integer同理

 

 

Comparator进行二分法

因为排序和查找要使用同一个Comparator,所以将后部分分离出来。

public static void main(String[] args) {
	Comparator<String> c=new Comparator<String>() {

		@Override
		public int compare(String o1, String o2) {
			// TODO Auto-generated method stub
			//o1和o2比较是升序
			//o2和o1比较是降序
			return o1.compareTo(o2);
		}
	};
	ArrayList<String> list = new ArrayList<String>();
	list.add("yz");
	list.add("gh");
	list.add("ef");
	list.add("cd");
	list.add("ab");
	System.out.println(list);
	Collections.shuffle(list);
	System.out.println(list);
	Collections.sort(list, c);
	System.out.println(list);
	System.out.println(Collections.binarySearch(list, "yz"));
}

定义了一个Comparator,无论是sort排序还是二分法查找,都可以直接调用

 

 

自定义元素对象的升序和降序

private static void test2() {
		ArrayList<Person> list = new ArrayList<Person>();
		list.add(new Person("wangwu",18));
		list.add(new Person("lisi",18));
		list.add(new Person("wangwu",28));
		list.add(new Person("zhaoliu",38));
		list.add(new Person("dahuang",8));
		//列表中的所有元素都必须实现 Comparable 接口
		Collections.sort(list);
		showList(list);
		
	}
	
	

	private static void showList(ArrayList<Person> list) {
		for(Person p : list){
			System.out.println(p);
		}
	}

 

 

 

 

如果使用Arrays和Collections的sort方法对象元素进行排序,这个列表元素必须实现Comparble类

public class Person implements Comparable<Person>{
	private String name;
	private int age;
	public Person() {
	}
	public Person(String name, int age) {
		this.name = name;
		this.age = age;
	}
	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;
	}
	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}
	@Override
	public int compareTo(Person o) {
		//this和o比较是升序
		//首先比较年龄是否相等,相等就比较姓名,如果不相等就直接比较年龄
		//return this.age==o.age?this.name.compareTo(o.name):this.age-o.age;
		
		
		//o和this比较是降序
		//首先比较姓名是否相等,相等就比较年龄,如果不相等就直接比较姓名
		return o.name.equals(this.name)?o.age-this.age:o.name.compareTo(this.name);
	}
}

 

 

比较器Comparator和Comparable接口同时存在时,以比较器为主。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值