04.尚学堂99-207.txt

UP 返回
1.容器
ArrayList初始容量为10
数组复制:System.arraycopy(src,srcPos,dest,destPos,length)		从src的srcPos位置向dest的destPos位置开始复制length长度的数据
LinkedList是一个双向链表

HashMap和HashTable一样的功能,前者线程不安全效率高,后者安全效率低
map的底层是数组+链表,,通过对hash值取余直接命中数组位置,通过链表处理冲突的元素。但是hashcode会存在负值,所以可以取绝对值再命中数组下标。
平时在使用hashcode时,如果需要保证一些散列问题,可以使用& Integer.MAX_VALUE 去符号,这只是为了解决负数问题,实际上会造成新的冲突

一般重写equals就会重写hashcode,这样保证了equals相同的对象hashcode一定相等,这是一个规范。如果不写或者重写成别的不合适的方式,会造成equals相同而hashcode不同

LinkedList里有一个查找方(查找之前判断下标位置,使查找变快):
	Node<E> node(int index) {
	        // assert isElementIndex(index);
	        if (index < (size >> 1)) {
	            Node<E> x = first;
	            for (int i = 0; i < index; i++)
	                x = x.next;
	            return x;
	        } else {
	            Node<E> x = last;
	            for (int i = size - 1; i > index; i--)
	                x = x.prev;
	            return x;
	        }
	    }

HashSet是由HashMap实现的,直接将值作为key塞入,value是一个new的Object

集合的循环:
Iterator iter = set.iterator();while(iter.hasNext())	或者	for(Iterator iter = set.iterator();iter.hasNext();)
通过Iterator中的游标来实现

map的循环:
Map <String,String>map = new HashMap<String,String>();
■1.最常见也是大多数情况下用的最多的,一般在键值对都需要使用
for(Map.Entry<String, String> entry : map.entrySet()){
    String mapKey = entry.getKey();
    String mapValue = entry.getValue();
}
■2.在for循环中遍历key或者values,一般适用于只需要map中的key或者value时使用,在性能上比使用entrySet较好
//key
for(String key : map.keySet()){
    System.out.println(key);
}
//value
for(String value : map.values()){
    System.out.println(value);
}
■3.通过Iterator遍历
Iterator<Entry<String, String>> entries = map.entrySet().iterator();
while(entries.hasNext()){
    Entry<String, String> entry = entries.next();
    String key = entry.getKey();
    String value = entry.getValue();
}
■4.通过键找值遍历,这种方式的效率比较低,因为本身从键取值是耗时的操作
for(String key : map.keySet()){
    String value = map.get(key);
}


2.泛型
2.1 概念:泛型就是参数化类型,使用广泛的类型
起因:数据类型不明确
	装入数据的类型都被当做Object对待,从而“丢失”自己的实际类型
	获取数据时往往需要转型,效率低,容易产生错误
作用:
	安全:在编译的时候检查类型安全
	省心:所有的强制转换都是自动和隐式的,提高代码的重用率

使用:
	泛型类需要在声明时使用泛型,泛型的字母可以任意设置,一般约定为:T  Type 表示类型;K V 分别代表键值中的Key Value;E 代表Element。 
	   在使用时需要确定泛型的类型
	注意:		
			泛型只能使用引用类型,不能基本类型
			泛型声明时字母不能使用在 静态属性|静态方法上(所以在接口中 泛型字母只能使用在方法中,不能使用在全局常量中)
			泛型的方法, <> 需要写在返回类型前面。只能访问对象的信息,不能修改信息
	代码:
				//泛型类
				public class Student<T1,T2> {
					private T1 javaScore;
					private T2 oracleScore;
					
					//▶泛型声明时不能使用 静态属性|静态方法上
					//private static T1 test;
		
					public static void main(String[] args) {
						//▶使用时指定类型(引用类型)
						Student<String,Integer> stu = new Student<String,Integer> ();
						//▶1、安全:类型检查
						stu.setJavaScore("优秀");
						//▶2、省心:类型转换
						int it =stu.getOracleScore(); //自动拆箱
					}
				}

				//泛型接口
				public interface Comparator<T> {
					void compare(T t);	
				}
				
				//泛型方法
				public class TestMethod {
					public static void main(String[] args) {
						test("a"); //T -->String
					}
				
					//泛型方法
					public static <T> void test(T a){		
						System.out.println(a);
					}
				
					// extends <=
					public static <T extends Closeable> void test(T... a){		
						for(T temp:a){
							try {
								if(null!=temp){
									temp.close();
								}
							} catch (IOException e) {
								e.printStackTrace();
							}
						}
					}
				}

2.2 泛型的继承:
	比如父类含有泛型(属性,方法),子类继承时可以有4中情况。继承时对泛型的处理:要么同时擦除,要么子类大于等于父类的类型;不能子类擦除,父类泛型
	   继承以后的属性类型
		在父类中,随父类而定
		在子类中,随子类而定
 	   继承以后方法重写:
 		方法中的泛型类型随父类而定
	代码
		//▶父类
		public abstract class Father<T,T1> {
			T name;
			public abstract void test(T t);
		}
		/**
		 * 情况1
		 * 子类声明时指定具体类型
		 * 属性类型为具体类型
		 * 方法同理
		 */
		class Child1 extends Father<String,Integer>{
			String t2;
			@Override
			public void test(String t) {
			}	
		}
		/**
		 * 情况2
		 * 子类为泛型类 ,类型在使用时确定
		 */
		class Child2<T1,T,T3> extends Father<T,T1>{
			T1 t2;
		
			@Override
			public void test(T t) {
				
			}
		}
		/**
		 * 情况3
		 * 子类为泛型类,父类不指定类型 ,泛型的擦除,使用Object替换
		 */
		class Child3<T1,T2> extends Father{
			T1 name2;
			@Override
			public void test(Object t) {
		
			}
		}
		/**
		 * 情况4
		 * 子类与父类同时擦除
		 */
		class Child4 extends Father{
			String name;	
			@Override
			public void test(Object t) {
				
			}
		}
		/**
		 *错误情况:子类擦除,父类使用泛型(不允许)
		class Child5 extends Father<T,T1>{
			String name;	
			@Override
			public void test(T t) {
				
			}
		*/
	 泛型接口与继承同理。重写方法随父类而定
		//父接口
		public interface Comparable<T> {
			void compare(T t);
		}
		//1.声明子类指定具体类型
		class Comp implements Comparable<Integer>{
			@Override
			public void compare(Integer t) {
				// TODO Auto-generated method stub
				
			}
			
		}
		//2.擦除
		class Comp1 implements Comparable{
			@Override
			public void compare(Object t) {
				// TODO Auto-generated method stub
		
			}
		}
		//3.父类擦除,子类泛型
		class Comp2<T> implements Comparable{
			@Override
			public void compare(Object t) {
				// TODO Auto-generated method stub
				
			}
		}
		//4.子类泛型>=父类泛型
		class Comp3<T> implements Comparable<T>{
			@Override
			public void compare(T t) {
				// TODO Auto-generated method stub
				
			}
		}

2.3 泛型没有多态,需要使用?来表示
	通配符?表示类型不定,使用时再确定类型。只能用在声明类型|声明方法上,不能声明类或使用时使用
  	? extends : <= 上限  指定类型 子类或自身
  	? super :>=下限   指定类型 为自身或父类
	代码:
		public class Student<T> {
			T score;
		
			public static void main(String[] args) {
				Student<?> stu = new Student<String>();
				test(new Student<Integer>());
				
				test2(new Student<Apple>());
				//test3(new Student<Apple>()); //泛型没有多态		
				
				//test4(new Student<Apple>()); //<
				 stu  = new Student<Fruit>();
				//test4(stu); //使用时确定类型
				test4(new Student<Object>());
				test4(new Student<Fruit>());
			}
			
			public static void test(Student<?> stu){
				
			}
			public static void test3(Student<Fruit> stu){
				
			}
			// <=
			public static void test2(Student<? extends Fruit> stu){
				
			}
			//>=
			public static void test4(Student<? super Fruit> stu){
				
			}
		}

2.4 泛型的嵌套:
	public class Bjsxt <T>{
	 T stu ;
	 
	 //Bjsxt和Student都是一个含有泛型的类,故可以嵌套使用。取值时一层层拆分
	 public static void main(String[] args) {
		 //泛型的嵌套 
		 Bjsxt<Student<String>> room =new  Bjsxt<Student<String>>();
		 //从外到内拆分
		 room.stu = new Student<String>();
		 Student<String> stu = room.stu;
		 String score =stu.score;
		 System.out.println(score);
	}
	}

2.5  没有泛型数组。 声明可以使用,但是创建失败
		//Student<String>[] arr2 = new Student<String>[10];	//错误
		Student<?>[] arr2 = new Student[10];
在jdk1.7中使用泛型,声明一次类型即可,在使用|创建时不用指定类型
		List<String>  arrList= new ArrayList<String>();
		List<String>  arrList2= new ArrayList<>();		//1.7以下会报错

2.6 以下这种写法不会报错:
int score =(int)obj; //jdk1.7以后 Object -->integer -->自动拆箱 可以自动发生
但是如果是1.7以下,必须用包装类:int score=(Integer)obj;

增强for中的被循环对象,必须实现java.lang.Iterable接口,重写iterator方法。其实现方式就是根据迭代器来的















DOWN 返回