ArrayList于LinkList(链表)
-
首先讲解一下LinkList,我们之前讲过动态数组ArrayList,ArrayList基于动态数组实现的非线程安全的集合;LinkedList基于链表实现的非线程安全的集合。
-
对于随机index访问的get和set方法,一般ArrayList的速度要优于LinkedList。因为ArrayList直接通过数组下标直接找到元素;LinkedList要移动指针遍历每个元素直到找到为止。
-
新增和删除元素,一般LinkedList的速度要优于ArrayList。因为ArrayList在新增和删除元素时,可能扩容和复制数组;LinkedList实例化对象需要时间外,只需要修改指针即可。
-
LinkedList集合不支持 高效的随机随机访问(RandomAccess)
-
ArrayList的空间浪费主要体现在在list列表的结尾预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗相当的空间
我们要使用java实现一个多级菜单,显而易见需要用到树形结构,那么怎样去写一个树形结构呢?
首先:我们创建一个TreeNode类:然后写一个Node的内部类:
public static class Node<T>{
private T data = null;
private List<Node<T>> children = new ArrayList<>();
private Node<T> parent = null;
}
接下来我们需要为他构建方法和设置get set方法:
public Node(T data) {
this.data = data;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public List<Node<T>> getChildren() {
return children;
}
public void setChildren(List<Node<T>> children) {
this.children = children;
}
public Node<T> getParent() {
return parent;
}
public void setParent(Node<T> parent) {
this.parent = parent;
}
/**
* 定义增加单个子节点的方法
*/
public Node<T> addChild(Node<T> child){
child.setParent(this); //this代表children对象本身
this.children.add(child);
return child;
}
/**
*添加多个子节点
*/
public void addChildren(List<Node<T>> children) {
children.forEach(each -> each.setParent(this));
this.children.addAll(children);
}
这里插入一下lambda表达式的讲解:
说白了就是 ->这个符号 前面写参数后面写方法:
// 1. 不需要参数,返回值为 5
() -> 5
// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x
// 3. 接受2个参数(数字),并返回他们的差值
(x, y) -> x – y
// 4. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)
然后我们需要往这个树里面添加节点,那么怎样添加呢?举个粒子:
Node<String> node1_china = new Node<String>("1.中国");
首先新建一个顶节点:node1_china
,然后为这个顶节点添加一个子节点:
Node<String> node1_1 = node1_china.addChild(new Node<String>("1.北京"));
这里的北京就是一个子节点使用了上面的addChild方法
Node<String> node1_1 = node1_china.addChild(new Node<String>("1.北京"));
不断的按照梯形去添加新的节点:
Node<String> node1_china = new Node<String>("1.中国");
Node<String> node1_1 = node1_china.addChild(new Node<String>("1.北京"));
Node<String> node1_1_1 = node1_1.addChild(new Node<String>("1.朝阳区")) ;
Node<String> node1_1_2 = node1_1.addChild(new Node<String>("2.海定区"));
Node<String> node1_1_3 = node1_1.addChild(new Node<String>("3.昌平区"));
Node<String> node1_2 = node1_china.addChild(new Node<String>("2.湖北"));
Node<String> node1_2_1 = node1_2.addChild(new Node<String>("1.武汉市")) ;
Node<String> node1_2_2 = node1_2.addChild(new Node<String>("2.襄樊市"));
Node<String> node1_2_3 = node1_2.addChild(new Node<String>("3.咸宁市"));
Node<String> node1_3 = node1_china.addChild(new Node<String>("3.湖南"));
Node<String> node1_3_1 = node1_3.addChild(new Node<String>("1.长沙市")) ;
Node<String> node1_3_2 = node1_3.addChild(new Node<String>("2.株洲市"));
Node<String> node1_3_3 = node1_3.addChild(new Node<String>("3.湘潭市"));
Node<String> node2_USA = new Node<String>("2.美国");
Node<String> node2_1 = node2_USA.addChild(new Node<String>("1.纽约市") ) ;
Node<String> node2_1_1 = node2_1.addChild(new Node<String>("1.曼哈顿"));
Node<String> node2_1_2 = node2_1.addChild(new Node<String>("2.布鲁克林"));
Node<String> node2_1_3 = node2_1.addChild(new Node<String>("3.皇后区"));
Node<String> node2_2 = node2_USA.addChild(new Node<String>("2.德克萨斯") ) ;
Node<String> node2_2_1 = node2_2.addChild(new Node<String>("1.奥斯汀"));
Node<String> node2_2_2 = node2_2.addChild(new Node<String>("2.休斯顿"));
Node<String> node2_2_3 = node2_2.addChild(new Node<String>("3.达拉斯"));
Node<String> node2_3 = node2_USA.addChild(new Node<String>("3.加利福尼亚") ) ;
Node<String> node2_3_1 = node2_3.addChild(new Node<String>("1.洛杉矶"));
Node<String> node2_3_2 = node2_3.addChild(new Node<String>("2.旧金山"));
Node<String> node2_3_3 = node2_3.addChild(new Node<String>("3.奥克兰"));
然后我们再定义一个顶尖节点,将两个定点放入:
Node<String> rootNode = new Node<String>("");
rootNode.addChild(node1_china);
rootNode.addChild(node2_USA);
接下来就需要要写打印输出的方法了:
为了可以有阶梯感,我们再构造打印方法的时候需要传入两个参数,一个就是要打印的树另一个是一个空格:
public static void printTree(Node<String> node, String appender){
System.out.println(appender+node.getData());
node.getChildren().forEach(each -> printTree(each,appender+appender));
}
全部代码:
package 任务三;
import 任务三.树形菜单.NewTest;
import java.util.ArrayList;
import java.util.List;
/**
* @author ${范涛之}
* @Description
* @create 2021-11-16 15:21
*/
public class TreeNode {
public static class Node<T>{
private T data = null;
private List<Node<T>> children = new ArrayList<>();
private Node<T> parent = null;
public Node(T data) {
this.data = data;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public List<Node<T>> getChildren() {
return children;
}
public void setChildren(List<Node<T>> children) {
this.children = children;
}
public Node<T> getParent() {
return parent;
}
public void setParent(Node<T> parent) {
this.parent = parent;
}
/**
* 定义增加单个子节点的方法
*/
public Node<T> addChild(Node<T> child){
child.setParent(this); //this代表children对象本身
this.children.add(child);
return child;
}
public void addChildren(List<Node<T>> children) {
children.forEach(each -> each.setParent(this));
this.children.addAll(children);
}
public static void main(String[] args) {
Node<String> node1_china = new Node<String>("1.中国");
Node<String> node1_1 = node1_china.addChild(new Node<String>("1.北京"));
Node<String> node1_1_1 = node1_1.addChild(new Node<String>("1.朝阳区")) ;
Node<String> node1_1_2 = node1_1.addChild(new Node<String>("2.海定区"));
Node<String> node1_1_3 = node1_1.addChild(new Node<String>("3.昌平区"));
Node<String> node1_2 = node1_china.addChild(new Node<String>("2.湖北"));
Node<String> node1_2_1 = node1_2.addChild(new Node<String>("1.武汉市")) ;
Node<String> node1_2_2 = node1_2.addChild(new Node<String>("2.襄樊市"));
Node<String> node1_2_3 = node1_2.addChild(new Node<String>("3.咸宁市"));
Node<String> node1_3 = node1_china.addChild(new Node<String>("3.湖南"));
Node<String> node1_3_1 = node1_3.addChild(new Node<String>("1.长沙市")) ;
Node<String> node1_3_2 = node1_3.addChild(new Node<String>("2.株洲市"));
Node<String> node1_3_3 = node1_3.addChild(new Node<String>("3.湘潭市"));
Node<String> node2_USA = new Node<String>("2.美国");
Node<String> node2_1 = node2_USA.addChild(new Node<String>("1.纽约市") ) ;
Node<String> node2_1_1 = node2_1.addChild(new Node<String>("1.曼哈顿"));
Node<String> node2_1_2 = node2_1.addChild(new Node<String>("2.布鲁克林"));
Node<String> node2_1_3 = node2_1.addChild(new Node<String>("3.皇后区"));
Node<String> node2_2 = node2_USA.addChild(new Node<String>("2.德克萨斯") ) ;
Node<String> node2_2_1 = node2_2.addChild(new Node<String>("1.奥斯汀"));
Node<String> node2_2_2 = node2_2.addChild(new Node<String>("2.休斯顿"));
Node<String> node2_2_3 = node2_2.addChild(new Node<String>("3.达拉斯"));
Node<String> node2_3 = node2_USA.addChild(new Node<String>("3.加利福尼亚") ) ;
Node<String> node2_3_1 = node2_3.addChild(new Node<String>("1.洛杉矶"));
Node<String> node2_3_2 = node2_3.addChild(new Node<String>("2.旧金山"));
Node<String> node2_3_3 = node2_3.addChild(new Node<String>("3.奥克兰"));
Node<String> rootNode = new Node<String>("");
rootNode.addChild(node1_china);
rootNode.addChild(node2_USA);
printTree(rootNode," ");
}
public static void printTree(Node<String> node, String appender){
System.out.println(appender+node.getData());
node.getChildren().forEach(each -> printTree(each,appender+appender));
}
}
}
心得:
这道题自己确实还是很不熟悉,感觉到了最后在用到遍历的时候还有Lambda表达式很生疏,现在自己理解一下:这是一个先输出再遍历的方法, System.out.println(appender+node.getData());
这里输出了我们的数据data也就是我们最一开始定义的第一个子节点:node1_china
,然后开始递归调用,通过foreach循环这个子节点的“子子”节点,“子子”节点的打印输出和最开始的node1_china
使用同样的方式, node.getChildren().forEach(each -> printTree(each,appender+appender));
也就是这行代码的后面那部分,我们创建了一个each临时变量来代替子节点、“子子”节点以及后面的“子子子节点”,通过->这个Lambda表达式,也就是“参数”->“方法”,实现遍历,这里的方法就是外面的printTree
方法。
打印输出的版本:
package 任务三;
import java.util.Scanner;
/**
* @author ${范涛之}
* @Description
* @create 2021-11-16 21:51
*/
public class TestNode2 {
public static void main(String[] args) {
/**
* 定义所有节点
*/
String s1 = "1.中国";
String s1_1 = "1.北京";
String s1_2 = "2.湖北";
String s1_3 = "3.湖南";
String s1_1_1 = "1.朝阳区";
String s1_1_2 = "2.海淀区";
String s1_1_3 = "3.昌平区";
String s1_2_1 = "1.武汉市";
String s1_2_2 = "2.襄樊市";
String s1_2_3 = "3.咸宁市";
String s1_3_1 = "1.长沙市";
String s1_3_2 = "2.株洲市";
String s1_3_3 = "3.湘潭市";
String s2 = "2.美国";
String s2_1 = "1.纽约州";
String s2_2 = "2.德克萨斯";
String s2_3 = "3.加利福尼亚";
String s2_1_1 = "1.曼哈顿";
String s2_1_2 = "2.布鲁克林";
String s2_1_3 = "3.皇后区";
String s2_2_1 = "1.奥斯汀";
String s2_2_2 = "2.休斯顿";
String s2_2_3 = "3.达拉斯";
String s2_3_1 = "1.洛杉矶";
String s2_3_2 = "2.旧金山";
String s2_3_3 = "3.奥克兰";
/**
* 使用多维数组存放
*/
String[] country = {s1, s2};
String[][] province = {{s1_1, s1_2, s1_3}, {s2_1, s2_2, s2_3}};
String[][][] position = {
{
{s1_1_1, s1_1_2, s1_1_3},
{s1_2_1, s1_2_2, s1_2_3},
{s1_3_1, s1_3_2, s1_3_3},
},
{
{s2_1_1, s2_1_2, s2_1_3},
{s2_2_1, s2_2_2, s2_2_3},
{s2_3_1, s2_3_2, s2_3_3},
}
};
System.out.println("请输入国家编号: 1:中国--2:美国");
Scanner scanner = new Scanner(System.in);
int t1 = scanner.nextInt();
while (true){
if (t1!=1 && t1!=2){
System.out.println("请输入1或者2");
continue;
}
else {
if (t1 == 1){
System.out.println(country[0]);
System.out.println("中国的省份有:1:北京 2:湖北 3:湖南");
}else {
System.out.println(country[1]);
System.out.println("美国的省份有:1:纽约 2:德克萨斯 3:加利福尼亚");
}
break;
}
}
System.out.println("请输入省份编号1-3");
int t2 = scanner.nextInt();
while (true){
if (t2!=1 && t2!=2 && t2!=3){
System.out.println("请输入1-3之间的数字");
continue;
}
else {
System.out.println(province[t1-1][t2-1]+"省的地区有:");
for (String s: position[t1-1][t2-1]) {
System.out.println(s);
}
break;
}
}
System.out.println("请输入地区编号1-3");
int t3 = scanner.nextInt();
while (true){
if (t3!=1 && t3!=2 && t3!= 3){
System.out.println("请输入1-3之间的数");
}
else {
System.out.println(position[t1-1][t2-1][t3-1]);
}
break;
}
}
}
参考了另一位同学的代码并作出了改进:完善了输出:
分割线———————————————————————————————————
分割线————————————————————————-
管道命令理解:就是前面命令的输出结果作为后面命令的输入结果:
明日再看…
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/81056.html