Vector特有功能:
import java.util.Enumeration; import java.util.Vector; /* Vector特有功能 添加功能:void addElement(E obj) 将指定的组件添加到此向量的末尾,将其大小增加 1。 ----add(); 获取功能:E elementAt(int index) 返回指定索引处的组件。 ----get(); Enumeration<E> elements() 返回此向量的组件的枚举。 ----Iterator(); boolean hasMoreElements() 测试此枚举是否包含更多的元素。 ----hasNext(); E nextElement() 如果此枚举对象至少还有一个可提供的元素,则返回此枚举的下一个元素。 ----next(); */ public class VectorDemo { public static void main(String[] args) { Vector<String> v = new Vector<>(); v.addElement("hello"); v.addElement("java"); v.addElement("world"); for(int i = 0; i < v.size(); i++){ String s = (String)v.elementAt(i); System.out.println("使用elementAt()返回指定位置的元素 " + s); } System.out.println("------------------------"); Enumeration en = v.elements(); while(en.hasMoreElements()){ String s = (String)en.nextElement(); System.out.println("使用特有迭代功能 " + s); } } }
LinkedList类概述
底层数据结构是链表,查询慢,增删快
线程不安全,效率高
import java.util.LinkedList; /* * LiknedList类特有功能 void addFirst(E e) 将指定元素插入此列表的开头 void addLast(E e) 将指定元素添加到此列表的结尾 E getFirst() 返回此列表的第一个元素。 E getLast() 返回此列表的最后一个元素。 E removeFirst() 移除并返回此列表的第一个元素。 boolean removeFirstOccurrence(Object o) 从此列表中移除第一次出现的指定元素(从头部到尾部遍历列表时)。 E removeLast() 移除并返回此列表的最后一个元素。 boolean removeLastOccurrence(Object o) 从此列表中移除最后一次出现的指定元素(从头部到尾部遍历列表时)。 */ public class LinkedListDemo { public static void main(String[] args) { LinkedList<String> ll = new LinkedList<>(); ll.add("hello"); ll.add("world"); ll.add("java"); ll.addFirst("添加到列表的开头"); ll.addLast("添加到列表的最后一位"); System.out.println("获取列表的第一个元素 " + ll.getFirst()); System.out.println("获取列表的最后一个元素 " + ll.getLast()); System.out.println("移除并返回列表的第一个元素 "+ ll.removeFirst()); System.out.println("移除并返回列表的最后一个元素 "+ ll.removeLast()); System.out.println("LinkedList的元素 " + ll); } }
去除重复元素:
import java.util.ArrayList; import java.util.Collection; public class rrayListDemo { public static void main(String[] args) { ArrayList<String> c = new ArrayList<>(); c.add("zed1"); c.add("zed1"); c.add("zed2"); c.add("zed3"); c.add("zed4"); c.add("zed5"); c.add("zed5"); System.out.println(c); //通过新建一个集合去除List集合中的重复元素 Collection<String> c2 = new ArrayList<>(); for(int i = 0; i < c.size();i++){ String s = (String) c.get(i); if(!c2.contains(s)){ c2.add(s); } } System.out.println("第一种方法去重复,c2的元素为: " + c2); //方法二:在同一个集合中操作 for(int i = 0; i < c.size(); i++){ for(int j = i + 1;j < c.size();j++){ if(c.get(i).equals(c.get(j))){ c.remove(c.get(j)); } } } System.out.println("第二种方法,c的元素为:" + c); } }
去重复的对象
Student类: //alt + shift + s 重寫equals方法 public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Student other = (Student) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } //---------------------------------------------------- import java.util.ArrayList; import java.util.Iterator; public class ArrayDemo2 { public static void main(String[] args) { ArrayList<Student> al = new ArrayList<>(); Student s1 = new Student("zed1", 1); Student s2 = new Student("zed1", 1); Student s3 = new Student("zed3", 3); Student s4 = new Student("zed3", 4); Student s5 = new Student("zed5", 5); Student s6 = new Student("zed6", 6); al.add(s1); al.add(s2); al.add(s3); al.add(s4); al.add(s5); al.add(s6); ArrayList<Student> al2 = new ArrayList<>(); Iterator it = al.iterator(); while(it.hasNext()){ Student s = (Student)it.next(); //如果Student类中没有重写euqals()方法,讲无法正确检测出是否重复。 if(!al2.contains(s)){ al2.add(s); } } for(int i = 0; i < al2.size(); i++){ Student s = (Student)al2.get(i); System.out.println(s.getName() + "---" + s.getAge()); } } }
contains()方法的底层是依赖equals()方法。
而我们学生类中没有equals()方法,这个时候,默认使用的是父类Object的euqals()方法。
Object的equals()方法默认比较的是地址值,所以new的东西地址值是不一样的。
按照我们的需求,比较成员变量的值,重写euqals()方法即可。
eclipse中ALT + SHIFT + S就自动重写euqals()方法。
//使用LinkedList模拟栈数据结果的集合。这里不是直接使用LinkedList集合,而是使用这种方式生成一个集合 import java.util.LinkedList; public class MyStackDemo { private LinkedList lst; public MyStackDemo(){ //构造器中初始化LinkedList,这样类初始化的时候实际初始化的是LinkedList对象 lst = new LinkedList(); } public void add(Object obj){ //MyStackDemo的添加方法实际时LinkedList的addFirst()方法 lst.addFirst(obj); } public Object get(){ //如果是getFirst()方法,实际会一直输出集合的第一个元素 //所以要使用removeFirst()方法,删除第一个元素并输出 //return lst.getFirst(); return lst.removeFirst(); } public boolean isEmpty(){ return lst.isEmpty(); } public static void main(String[] args){ MyStackDemo ms = new MyStackDemo(); ms.add("hello"); ms.add("world"); ms.add("java"); /* 注:这样联系三次是没有问题的,因为集合有三个元素,但是如果联系输出四次就会出错,因为集合没有那么多元素 所以可以使用isEmpty()方法判断,不为空则输出 System.out.println(ms.get()); System.out.println(ms.get()); System.out.println(ms.get());*/ while(!ms.isEmpty()){ System.out.println(ms.get()); } } }
泛型
public class ArrayTest{ public static void main(String[] args){ ArrayList al = new ArrayList(); al.add("hello"); al.add("world"); al.add("java"); al.add(10); //al.add(Integer.valueOf(10)); Iterator it = al.iterator(); while(it.hasNext()){ //这样编译的时候会报错,因为10是Integer类型的,无法转换成String类型 //classcastException异常 String s = (String)it.next(); System.out.println(s); } } }
对迭代器使用泛型
//对迭代器使用泛型 Iterator<Student> it = al.iterator(); while(it.hasNext()){ //对迭代器使用泛型,这里就不需要强制类型转换,迭代器中只会存在泛型的类型 Student s = it.next(); if(!al2.contains(s)){ al2.add(s); } }
for(int i = 0; i < al2.size(); i++){ //集合使用了泛型用for循环遍历就不需要强制类型转换 Student s = al2.get(i); System.out.println(s.getName() + "---" + s.getAge()); }
//下面命令是泛型推断,不建议这样 ArrayList<Student> al = new ArrayList<>(); //建议写全 ArrayList<Student> al = new ArrayList<Student>();
泛型:是一种把类型明确的工作推迟到创建对象或者调用方法的时候才去明确的特殊的类型,也称为参数化类型,把类型当错参数一样传递。
格式:
<数据类型>
此处的数据类型只能是引用类型。
//下面命令错误,int是基本数据类型,不是引用类型 //Student<String,int> s = new Student<String,int>(); Student<String,Integer> s = new Student<String,Integer>();
好处:
把运行时的问题提前到了编译器;
避免了强制类型转换
优化程序设计
泛型在哪些地方使用?
看API,如果类、接口、抽象类后面跟的有<E>就说要用泛型,一般来说在集合中使用。
泛型类
把泛型定义在类上
格式:public class 类名<泛型类型, ...>
注意:泛型类型必须是引用类型
//泛型类 class Person<S, TNI>{ public S name; public TNI age; public Person() { // TODO 自动生成的构造函数存根 } public Person(S name, TNI age) { this.name = name; this.age = age; } public S getName() { return name; } public void setName(S name) { this.name = name; } public TNI getAge() { return age; } public void setAge(TNI age) { this.age = age; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } public <TNI>void geth(TNI age) { // TODO 自动生成的方法存根 System.out.println(age); } } public class Student<S, TNI> extends Person<S, TNI>{ private S name; private TNI age; public Student(S name,TNI age){ this.name = name; this.age = age; } public Student() {} public S getName() { return name; } public void setName(S name) { this.name = name; } public TNI getAge() { return age; } public void setAge(TNI age) { this.age = age; } public S geth(){ return name; } @Override public String toString() { return "name " + name + "----" + "age " + age; } } /*-----------------------------------------------------*/ public class Demo { public static void main(String[] args) { //下面命令错误,int是基本数据类型,不是引用类型 //Student<String,int> s = new Student<String,int>(); Person<String,String> s = new Student<String,String>(); s.setName("zed"); s.setAge("10"); System.out.println(s); s.<Integer>geth(10); System.out.println("-------------------------"); Student<String,Integer> s2 = new Student<String,Integer>(); s2.setName("zed2"); s2.setAge(18); System.out.println(s2); s.<String>geth("输出字符串"); } }
泛型方法
把泛型定义在方法上
格式:public <泛型类型> 返回类型 方法名(泛型类型)
public class Demo { //泛型方法 public <T, S> void get(T t, S s){ System.out.println(t + "---" + s); } public static void main(String[] args) { //泛型方法的调用 Demo d = new Demo(); d.<String,Integer>get("呵呵", 11); d.<Integer,String>get(100, "呵呵"); } }
泛型接口
把泛型定义在接口上
格式:public interface 接口名<泛型类型1, ...>
泛型通配符
泛型通配符
任意类型,如果没有明确,name就是Object以及任意的Java类
? extends E
向下限定,E及其子类
? super E
向上限定,E及其父类
//下面命令是错误的,Collection<?> 可以,但是new对象的时候ArrayList<?>需要明确的类型 //Collection<?> c = new ArrayList<?>(); Collection<?> c = new ArrayList<Object>(); //泛型明确的写的时候,前后必须一致,而用通配符就可以避免这种情况 //Collection<Object> c = new ArrayList<String>();
JDK5的新特性:自动拆装箱、泛型、增强for、静态导入、可变参数、枚举...
增强for方法:
for(元素数据类型 变量 : 数组或Collection集合){ 使用变量即可,该变量就是元素 }
Person<String, Integer> s2 = new Student(); s2.setAge(18); // Student类中下面命令会导致age无法传入到对象中,因为父类对象中age是Integer引用类型,泛型变量无法向上转型 // 并不会主动向上转型,改为 public void setAge(Integer age)就可以正确传入元素数据,因为这个类是从泛型父类继承过来,父类中泛型只能是引用类型,继承过来的数据类型也只能是引用类型 // public void setAge(int age) { // this.age = age; // } s2.setName("zed2"); System.out.println(s2);
可变参数概述
定义方法的时候不知道定义多少个参数
格式
修饰符返回值类型 方法(数据类型... 参数名){}
注意:
这里的变量其实是一个数组
如果一个方法有可变参数,并且有多个参数,那么可变参数肯定是最后一个
public class FORTest { public void test(int i, String... s) { for (String ss : s) { System.out.println(i); System.out.println(ss); } } public void test2(int i, String[] s) { for (String ss : s) { System.out.println(i); System.out.println(ss); } } public static void main(String[] args) { FORTest f = new FORTest(); f.test(1, "zed1", "zed2", "zed3", "zed4"); System.out.println("--------------"); //注意:new String[]{}; f.test2(2, new String[] { "zed5", "zed6", "zed7" }); } }
String[] strArray = {"hello","world","java"}; //把数组转换为集合 List<String> list = Arrays.asList(strArray); //先定义一个数组,把数组传入asList()方法或者直接传入数组元素都可以 //List<String> list = Arrays.asList("hello", "world", "java"); //通过asList()方法转换的集合无法增加删除,但可以修改 //虽然可以把数组转换为集合,其本质还是数组,数组长度是不变的,所以无法增删。 //list.add("javaee"); //list。remove("java"); list.set(1, "javaee");
使用类、接口时也可以不为类型形参传入实际的参数。静态方法、静态初始化块或静态变量的声明和初始化不允许使用类型形参,本身属于类的长远应该是明确的、固定的。
集合嵌套遍历
import java.util.ArrayList; class Test { private String name; private int age; public Test() { } public Test(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 "Student [name=" + name + ", age=" + age + "]"; } } public class CollectionTest4 { public static void main(String[] args) { ArrayList<ArrayList<Test>> aas = new ArrayList<ArrayList<Test>>(); ArrayList<Test> as = new ArrayList<Test>(); Test s1 = new Test("zed1", 1); Test s2 = new Test("zed2", 2); Test s3 = new Test("zed3", 3); as.add(s1); as.add(s2); as.add(s3); ArrayList<Test> as2 = new ArrayList<Test>(); Test s4 = new Test("zed4", 4); Test s5 = new Test("zed5", 5); Test s6 = new Test("zed6", 6); as2.add(s4); as2.add(s5); as2.add(s6); ArrayList<Test> as3 = new ArrayList<Test>(); Test s7 = new Test("zed7", 7); Test s8 = new Test("zed8", 8); Test s9 = new Test("zed9", 9); as2.add(s7); as2.add(s8); as2.add(s9); aas.add(as); aas.add(as2); aas.add(as3); //ArrayList<ArrayList<Test>> aas = new ArrayList<ArrayList<Test>>(); //ArrayList<Test>类型元素aas //Test元素外层for循环下的元素a for (ArrayList<Test> a : aas) { for (Test b : a) { System.out.println(b.getName() + " -----" + b.getAge()); } } } }