package cm;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

public class test20180409 {

	public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
		// int[] data = {1,2,3,4,5};
		//
		// List list = Arrays.asList(data);
		//
		// System.out.println("列表中的元素数量是:" + list.size());
		// 注意这里输出的数量是1,原因是,在Arrays.asList中,该方法接受一个变长参数,一般可看做数组参数,但是因为int[]
		// 本身就是一个类型,所以data变量作为参数传递时,编译器认为只传了一个变量,这个变量的类型是int数组,所以size为1。基本类型是不能作为泛型的参数,按道理应该使用包装类型,但这里缺没有报错,因为数组是可以泛型化的,所以转换后在list中就有一个类型为int的数组

		// List ss=Arrays.asList("a","b");
		// ss.add("s");这里使用add方法会出错,因为使用arrays.aslist()方法处理过的数据,返回的list类型,已经不是传统意义上的list了,此list没有实现add方法,需要自己手动实现

		// List常用的有两种实现Arraylist和LinkedList
		// ArrayList的特点在于随机访问元素,内部由数组实现,缺点插入和移除元素比linkedList开销大。
		// 接口List最重要的特点是次序,它维护了元素的特定顺序.一个List可以生成listiterator,用于遍历list中的元素
		// LinkedList中的方法addfirst(),addLast(),getfirst(),getLast(),removefirst(),removelast()使得Linkedlist可以当做堆栈,队列,双向队列等数据结构使用。
		// List a = new LinkedList();
		// a.add("1");
		// a.add("2");
		// a.add(1, "3");// 将3插入index为1处
		// ArrayList arr = new ArrayList();
		// arr.add("Hi");
		// a.addAll(arr);// 将一个collection添加进linkedlist
		// a.addAll(1, arr);// 将一个collection从index为1处开始添加
		// Boolean is = a.contains("1");// true 检车linkedlist中是否包含字符串1.
		// Boolean isarr = a.containsAll(arr);// true 判断linked中是否包含arr容器。
		// String str = a.get(1).toString();// 返回索引为1的对象,调用对象的tostring将对象以可读的方式输出。
		// int index = a.indexOf("Hi");// 返回第一个匹配的索引。
		// boolean isempty = a.isEmpty();// 判断LinkedList容器是否为空
		// a.remove(3);// 移除索引为3的元素
		// a.remove("Hi");// 移除元素Hi
		// ;// 将索引为1处的元素改为be3
		// a.removeAll(arr);// 参照容器arr将a中元素移除
		// // a.clear();//清除a中的所有元素
		// Iterator it = a.iterator();// 将容器Linkedlist转换为一个迭代器
		// ListIterator itt = a.listIterator();//
		// 将容器linkedlist转换成listiterator。listiterator和iterator的主要区别是
		// listiterator只能应用于list集合,及其子集,而iterator能应用于所有集合。listiterator支持向前和向后遍历,而iterator只支持向后遍历。listiterator还支持向集合中添加元素add()方法
		// // Iterator it3=a.listIterator(1);//将容器Linkedlist转换为一个迭代器,从容器索引为3的地方开始。
		// boolean hn = itt.hasNext();// 判断迭代器中是否还有下一个元素
		// Boolean hp = itt.hasPrevious();
		// String sn = (String) itt.next();
		// int ni=itt.nextIndex();
		// String sp = (String) itt.previous();
		// int pi=itt.previousIndex();
		// itt.add("47");//向listiterator中添加元素
		// P.sopl(isarr + "");
		// P.sopl(is + "");
		// P.sopl(a + "");
		// P.sopl(str);
		// P.sopl(index + "");
		// P.sopl(isempty + "");
		// P.sopl(hn + "");
		// P.sopl(hp + "");
		// P.sopl(sn);
		// P.sopl(ni+"");
		// P.sopl(sp);
		// P.sopl(pi+"");

		// 使用Linkedlist制作一个栈(后进先出结构)
		// stacklist st=new stacklist();
		// st.push(new String("i love you"));
		// st.push(new String("i love you too"));
		// P.sopl(st.top().toString());
		// P.sopl(st.pop().toString());
		// P.sopl(st.top().toString());

		// 使用linkedlist制作一个队列,即先进先出结构,可用来制作queue类
		// queuelist ql=new queuelist();
		// ql.put(new String("ok"));
		// P.sopl(""+ql.isEmpty());
		// P.sopl(""+ql.get());
		// P.sopl(""+ql.isEmpty());

		// set的功能和方法
		// 前提:set集合不保存相同的元素,存入set的元素必须实现equals方法用于判断元素的唯一性,set和collection接口具有完全一样的接口。set不保证存入元素的次序。
		// hashset目的是为了实现快速查找,存入hashset的元素对象必须实现hashcode()方法。treeset是保持次序的set,它可以从set中提取有序的序列,比较顺序是按照元素的comperto比较方法进行比较的。
		// linkedhashset,具有hashset的查询速度,内部使用链表维护元素的顺序,使用迭代器遍历set时,结果会以元素插入的顺序显示。
		// settest sett = new settest();
		// sett.test(new HashSet());
		// sett.test(new TreeSet<>());
		// sett.test(new LinkedHashSet<>());

		// sortedset是treeset的一个接口,treeset是其的唯一实现。

		// Map的功能方法
		// P.sopl(Integer.toString(new
		// String("o1dafk").hashCode()));//测试string类是否实现了hashcode方法。
		// hashmap插入和查询键值对的开销是固定的,可以通过调整构造器来调整hashmap的容量和负载因子来调整hashmap的性能。
		// linkedhashmap取得键值对的顺序是插入键值对的顺序,比hashmap慢一点,但是在使用迭代器访问时linkedhashmap快一些,因为linkedhashmap内部使用链表实现的。
		// treemap取得键值对或则健的时候是经过排序的,次序由cpmpareable和cpmparator方法决定。
		// weakhashmap,如果没有map之外的引用指向某个键,则此键将被回收。

		// hashmap
		// Map hm=new HashMap<>();
		// Random rand=new Random();
		// for (int i = 0; i < 10000; i++) {
		// Integer in=new
		// Integer(rand.nextInt(20));//为什么这里使用包装器类,because所有的容器都只能存放对象的引用,而不能存放基本类型
		// if(hm.containsKey(in)) {
		// ((counter)hm.get(in)).i++;//这里为什么用到自定义的counter类,而不用包装起来integer,因为包装器类只能在声明的时候读入一个值,也就是初始化一个值,并且读取这个值,生成一个对应类型的对象,之后就不能修改这个包装器的值了,没有提供对应的修改方法。
		// }else {
		// hm.put(in, new counter());
		// }
		// }
		// P.sopl(hm.toString());

		// Linkedhashmap
		// LinkedHashMap<String,String> ls=new
		// LinkedHashMap<>(20,0.1f,true);//第三个参数true用于实现LRU,根据访问顺序进行排序,最新访问的数据放在容器的最后。第一个参数13用于提供给这个类的基类用于初始化数组的容量,第二个参数代表负载因子。
		// P.sopl(ls.getClass()+"");
		// ls.put("1","a");
		// ls.put("2","b");
		// ls.put("3","c");
		// ls.get("1");
		// ls.get("2");
		// for(Map.Entry<String, String> entry:ls.entrySet())
		// {//使用Map接口的entry,Linkedhashmap类的entryset方法将容器中的键值对封装成一个一个的对象用于遍历
		// P.sopl(entry.getKey()+entry.getValue());
		// }
		// // P.sopl(ls.toString());

		// tips:调用类对象实例化一个对象
		// 1. 通过类对象调用newInstance()方法,适用于无参构造方法:
		// 例如:String.class.newInstance()
		// Solution solution = Solution.class.newInstance();
		// Solution solution2 = solution.getClass().newInstance();
		// Class solutionClass = Class.forName("Solution");
		// Solution solution3 = (Solution) solutionClass.newInstance();
		// 2.通过类对象调用getConstructor()方法,此方法接受参数是一个Class类型的数组,数组中存放的是各个类类对象(类名.class),getConstructor()方法根据class数组中类对象的类型选择声明的构造器。
		// Class []cs= {int.class};
		// counter c=counter.class.getDeclaredConstructor(cs).newInstance(22);
		// P.sopl(c.toString());

		// hashcode算法和散列码
		// 任何不特殊说明的类默认继承object基类,而object基类中的hashcode算法是根据对象的地址来生成散列码的。
		// 测试
		// counter ct = new counter();
		// counter ct2 = new counter();
		// P.sopl(Integer.toString(ct.hashCode()));
		// P.sopl(Integer.toString(ct2.hashCode()));//
		// 这两个对象完全一样,除了在堆中的地址不一样,所以生成的散列码就不一样。
		//hashmap用equals方法判断传入的参数键是否存在于表中。hashmap中的equals方法并没有从写,而是继承了基类object中的equals方法,object中的equals方法只是比较两个引用(地址)是否相等,即是否指向同一个堆中的对象。

	}

}

class stacklist {
	private LinkedList<Object> list = new LinkedList<>();

	public void push(Object o) {
		list.addFirst(o);
	}

	public Object top() {
		return list.getFirst();
	}

	public Object pop() {
		return list.removeFirst();
	}
}

class queuelist {
	private LinkedList<Object> list = new LinkedList<>();

	public void put(Object o) {
		list.addFirst(o);
	}

	public Object get() {
		return list.removeLast();
	}

	public Boolean isEmpty() {
		return list.isEmpty();
	}
}

class settest {
	public static void fill(Set s) {
		s.addAll(Arrays.asList("i love you do you".split(" ")));
	}

	public static void test(Set s) {
		fill(s);
		P.sopl(s.getClass().getName().replaceAll("\\w+\\.", ""));
		P.sopl(s + "");
	}
}

class counter {
	int i = 1;

	public counter(int x) {
		i = x;
	}

	public String toString() {
		return Integer.toString(i);
	}
}