java 泛型(Generic)和Collection

泛型(Generic)

泛型的概述:泛型是一种将类型的确定提前到编译时期的一种参数化类型。

格式:

泛型只允许设置引用数据类型,这里的E可以是A~Z任意一个字母。

泛型的分类:

泛型类:把泛型定义在类上

泛型接口:把泛型定义在接口上

泛型方法:把泛型定义在方法上

泛型的好处:

1.消除了黄色警告线

2.去除类型转换(例如不用讲Object类向下转型),提高了效率。

3.提高了安全性,避免了类型转换异常。

4.简化了代码。

5.提高了代码的扩展和可维护性。

泛型的特点:

1.泛型具有传递性

2.泛型可以定义多个

3.泛型只能设置引用数据类型

4.泛型的命名可以是A~Z之间

public class GenericDemo01 {
	public static void main(String[] args) {
		Collection<String> c = new ArrayList<String>();
		c.add("三国演义");
		c.add("水浒传");
		c.add("红楼梦");
		c.add("西游记");
		Iterator<String> it = c.iterator();
		while (it.hasNext()) {
			String s = it.next();
			System.out.println(s + "|" + s.length());
		}
		for (String s : c) {
			System.out.println(s + "|" + s.length());
		}
	}
}
泛型类:
public class GenericDemo02 {
	public static void main(String[] args) {
		GenericClass<String, Float, Character> gc = new GenericClass<String, Float, Character>();
		gc.setF('A');
		gc.setH(3.55f);
		gc.setT("小明");

	}
}

//泛型可以定义多个
class GenericClass<T, H, F> {
	private T t;
	private H h;
	private F f;

	public GenericClass() {
	}

	public GenericClass(T t, H h, F f) {
		super();
		this.t = t;
		this.h = h;
		this.f = f;
	}

	public T getT() {
		return t;
	}

	public H getH() {
		return h;
	}

	public void setH(H h) {
		this.h = h;
	}

	public F getF() {
		return f;
	}

	public void setF(F f) {
		this.f = f;
	}

	public void setT(T t) {
		this.t = t;
	}

}
泛型接口

使用泛型接口的三种方式

1.在实现类的时候确定泛型类型

2.在实现类的时候不确定泛型类型,在创建接口的时候确定泛型类型。

3.在匿名内部类的时候确定泛型类型。

public class InterfaceDemo01 {
	public static void main(String[] args) {
		IGeneric<Integer, String> gi = new GenericImpl();
		gi.show("小明");
		gi.concat(20, "老王");

		//在创建接口的时候确定泛型
		IGeneric<String, Double> gi2 = new GenericImpl2<String, Double>();
		gi2.show(6.66);
		gi2.concat("小张", 6.66);

		//在匿名内部类的时候确定泛型
		IGeneric<String, Integer> gi3 = new IGeneric<String, Integer>() {
			@Override
			public void show(Integer t) {
				System.out.println("Hello" + t);
			}

			@Override
			public void concat(String e, Integer r) {
				System.out.println(e + r);
			}
		};
		gi3.show(100);
		gi3.concat("你好", 88);
	}
}

interface IGeneric<E, T> {
	void show(T t);

	void concat(E e, T r);
}

//在实现类的时候确定接口类型
class GenericImpl implements IGeneric<Integer, String> {

	@Override
	public void show(String t) {
		System.out.println(t);
	}

	@Override
	public void concat(Integer e, String r) {
		System.out.println(r + e);
	}

}

//在实现类的时候也不确定接口类型
class GenericImpl2<E, T> implements IGeneric<E, T> {

	@Override
	public void show(T t) {
		System.out.println(t);
	}

	@Override
	public void concat(E e, T r) {
		System.out.println(e);
		System.out.println(r);
	}

}
泛型方法

使用泛型方法:在方法调用的时候确定泛型

特点:

1.泛型方法在方法调用的时候确定类型

2.泛型方法独立于泛型类,泛型方法又称为局部泛型

3.泛型方法也可以定义多个。

public class GenericDemo04 {
	public static void main(String[] args) {
		GenericMethod<String, Integer> gm = new GenericMethod<String, Integer>();
		System.out.println(gm.show(200));
		gm.test("ad", 100);
		
	}
}

class GenericMethod<E, T> {
	private E e;
	private T t;

	public GenericMethod() {
		super();
	}

	public GenericMethod(E e, T t) {
		super();
		this.e = e;
		this.t = t;
	}

	public <X> X show(X x) {
		return x;
	}

	public <K, V> void test(K k, V v) {
		System.out.println(k.getClass().getName());
		System.out.println(v.getClass().getName());
	}

	public E getE() {
		return e;
	}

	public void setE(E e) {
		this.e = e;
	}

	public T getT() {
		return t;
	}

	public void setT(T t) {
		this.t = t;
	}

}

集合转数组;数组转集合
public class GenericDemo05 {
	public static void main(String[] args) {
		Collection<String> c = new ArrayList<String>();
		c.add("a");
		c.add("b");
		c.add("c");
		//将集合转数组
		String[] str = c.toArray(new String[] {});
		for (String s : str) {
			System.out.println(s);
		}
		//将数组转集合 T[]
		Integer[] arr = { 11, 22, 33 };
		List<Integer> asList = Arrays.asList(arr);
		for (Integer ii : asList) {
			System.out.println(ii);
		}
	}
}
泛型限定符
  • <?> 代表任意类型
  • <? extends E> 代表泛型可以是E类型或者是E的子类
  • <? super T> 代表泛型可以是T类型或是T的父类
泛型嵌套

概述:泛型里面定义泛型

public class GenericDemo07 {
	public static void main(String[] args) {
		Collection<Student> ac = new ArrayList<Student>();
		ac.add(new Student("张三", 30));
		ac.add(new Student("李四", 35));
		ac.add(new Student("王五", 40));
		
		Collection<Student> bc = new ArrayList<Student>();
		bc.add(new Student("赵六", 30));
		bc.add(new Student("孙七", 35));
		
		Collection<Student> cc = new ArrayList<Student>();
		cc.add(new Student("隔壁老王", 30));
		
		Collection<Collection<Student>> classes = new ArrayList<Collection<Student>>();
		classes.add(ac);
		classes.add(bc);
		classes.add(cc);
		
		/*Iterator<Collection<Student>> iterator = classes.iterator();
		while (iterator.hasNext()) {
			Collection<Student> c = iterator.next();
			Iterator<Student> it = c.iterator();
			while (it.hasNext()) {
				Student s = it.next();
				System.out.println(s.getName() + "|" + s.getAge());
			}
		}*/
		
		for (Collection<Student> collection : classes) {
			for (Student s : collection) {
				System.out.println(s.getName() + "|" + s.getAge());
			}
		}
	}
}

集合

集合是一批类,它是一套框架体系。

一:. 集合为什么要设计出这么多类?

集合分为单列集合和双列集合,单列集合类似于数组存储一组数据,双列集合存储具有关系两列数据,并且有很多不同数据结构的子类,所以设计很多类组合而成

二:. 集合顶层父类为什么设计成接口而不设计成普通类?

因为我们认为容器中的元素又不同的特点:

a. 是否有序 【存储有序,怎么样存进去的就怎样出来】

数据结构 【数据的存储方式】

b. 是否唯一

c. 是否可排序

d. 是否安全

针对不同的特点会有不同的实现,那么这个时候父类必须设计成接口,子类根据不同的数据结构和实现方式实现自己的增删查改的功能,所以父类设计为接口

数组和集合的区别

长度

数组的长度固定不变的

集合长度是可以根据实际需要改变

内容

数组存储的是同一种类型的元素

集合可以存储不同类型的元素

数据类型

数组可以存储基本数据类型,也可以存储引用数据类型

集合只能存储引用类型

注意:虽然集合不能存储基本数据类型,但是可以存储基本数据类型的包装类类型

public class CollectionDemo01 {
	public static void main(String[] args) {
		Collection<String> c = new ArrayList<String>();
		c.add("老王");
		c.add("老李");
		c.add("老张");
		System.out.println(c);//[老王, 老李, 老张]
		c.remove("老李");
		System.out.println(c);//[老王, 老张]
		Collection<String> c2 = new ArrayList<String>();
		c2.add("10");
		c2.add("20");
		c.addAll(c2);//[老王, 老张, 10, 20]
		System.out.println(c);
		c.retainAll(c2);//取交集
		System.out.println(c);//[10, 20]		
	}
}

集合的遍历

一: toArray遍历方式:将集合转换成数组进行遍历

二:1. 迭代器遍历:// 通过集合创建迭代器对象

​ Iterator it = c.iterator();

Foreach遍历集合

Foreach遍历集合的格式:

For(元素类型 元素名 : 集合) {

通过元素名操作元素;

}

  1. foreach简化遍历

  2. Foreach本质还是使用了迭代器

    ​ Object obj;

​ for (Iterator iterator = c.iterator(); iterator.hasNext(); System.out.println(obj))

​ obj = iterator.next();

  1. Foreach遍历集合和while的区别

    (1) Foreach遍历之后就会释放迭代器对象,节约内存

    (2) While循环遍历集合可读性更强

    并发修改异常

    java.util.ConcurrentModificationException

    异常名称: 并发修改异常

    产生原因: 在遍历迭代器对象元素的同时使用集合对象修改了元素

    解决办法:

     	1.可以遍历原集合并且使用原集合修改
    
     			toArray
    
     			如果是List接口的子集合还可以使用 普通for
    
     	2.使用迭代器遍历并且使用迭代器修改
    
     			后期可以使用 ListIterator 进行处理
    
    public class CollectDemo02 {
    	public static void main(String[] args) {
    		Collection<String> c = new ArrayList<String>();
    		c.add("张三");
    		c.add("李四");
    		c.add("王五");
    		c.add("赵六");
    		c.add("孙七");
    
    		// 需求: 如果集合中存在李四,就删除李四
    		//遍历原集合并且使用原集合修改
    		Object[] objs = c.toArray();
    		for (Object obj : objs) {
    			if (obj.equals("李四")) {
    				c.remove("王五");
    			}
    		}
    		System.out.println(c);
    	}
    }
    

    Collection集合去除重复元素

    1. 创建一个新的集合,然后使用地址传递

      (1) 如果比较的是系统类,String 不需要重写equals方法

      (2) 如果比较的是自定义对象,需要自己根据需求重写equals方法

/*1.创建员工类 (编号 姓名 年龄 工资)
2.使用集合存储 员工 (要求存储重复元素  id编号相同即为重复)
3.遍历集合,输出所有员工信息 (要求至少使用4种遍历方式)
4.去除集合中的重复元素*/
public class CollectionDemo {
	public static void main(String[] args) {
		Collection c = new ArrayList();
		Employee e1 = new Employee("1001", "小李", 20, 5000);
		Employee e2 = new Employee("1002", "小王", 20, 4000);
		Employee e3 = new Employee("1003", "小张", 22, 6000);
		Employee e4 = new Employee("1004", "小孙", 28, 8000);
		Employee e5 = new Employee("1001", "小李", 20, 5000);
		Employee e6 = new Employee("1002", "小王", 20, 4000);
		//往集合添加元素
		c.add(e1);
		c.add(e2);
		c.add(e3);
		c.add(e4);
		c.add(e5);
		c.add(e6);
		//循环遍历
		//方法一:for循环
		Object[] obj = c.toArray();
		for (int i = 0; i < obj.length; i++) {
			System.out.println(obj[i]);
		}
		System.out.println("========================");
		//方法二:foreach循环
		for (Object obj1 : c) {
			System.out.println(obj1);
		}
		System.out.println("========================");
		//方法三:while循环
		/*
		 * 有下一个元素,则输出下一个元素
		 * 没有下一个元素,退出循环 
		 * //创建集合迭代器
		 */
		Iterator it = c.iterator();
		while (it.hasNext()) {
			System.out.println(it.next());
		}
		System.out.println("=========================");
		//去除集合中重复的元素
		Collection c1 = new ArrayList();
		// 遍历旧集合
		for (Object obj2 : c) {
			//判断新集合是否包含该元素
			if (!c1.contains(obj2)) {
				//如果不包含的话就添加该元素
				c1.add(obj2);
			}
		}
		//地址传递
		c = c1;
		for (Object obj3 : c) {
			System.out.println(obj3);
		}

		System.out.println("=========================");
		c.remove(e2);
		c.remove(e3);
		for (Object object : c) {
			System.out.println(object);
		}
		System.out.println("=========================");
		c.add(new Employee("1008", "老昂", 3985, 18));
		for (Object object4 : c) {
			System.out.println(object4);
		}
	}
}

//创建员工类
class Employee {
	private String id;
	protected String name;
	private double salary;
	private int age;

	public Employee() {

	}

	public Employee(String id, String name, double salary, int age) {
		this.id = id;
		this.name = name;
		this.salary = salary;
		this.age = age;
	}

	@Override
	public String toString() {
		return "Employee [id=" + id + ", name=" + name + ", salary=" + salary + ", age=" + age + "]";
	}
	

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode());
		return result;
	}

	@Override//重写equals方法
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Employee other = (Employee) obj;
		if (id == null) {
			if (other.id != null)
				return false;
		} else if (!id.equals(other.id))
			return false;
		return true;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值