英文:
Do the methods used in if statement tests execute?
问题
免责声明:我是一名新手程序员,只有几个月的经验,如果这个问题很简单,我深感抱歉。
在Java中,if语句中的方法会被执行吗?
例如,在这段代码中,我有一个名为waitlist的变量,类型是LinkedListQueue,这是我编写的一个模拟队列数据结构的类,其中包含enqueue()(添加)、dequeue()(移除)、size、setCapacity和isEmpty()等方法。dequeue()方法会返回从队列中移除的对象。waitlist变量是一个int类型的LinkedQueue对象。我想遍历队列的每个元素,并检查是否等于3,如果是,我将把它移除。当if语句测试的那行代码执行时,它会移除队列中的对象吗?
for (int i = 0; i < waitlist.size(); i++) {
if (waitlist.dequeue() == 3) {
waitlist.dequeue();
}
}
英文:
Disclaimer: I am a new programmer with only a few months of experience so I apologize if this question is trivial.
In Java, do the methods in the test of an if statement execute?
For example, in this snippet of code, I have a waitlist variable of type LinkedListQueue, which is a class that I wrote to model a queue data structure, with methods for enqueue() (add), dequeue() (remove), size, setCapacity, and isEmpty(). The dequeue() method returns the object removed from the queue. The waitlist variable is a LinkedQueue object of type int. I want to traverse through each element of the queue and check if it equals 3, and if it does, I will remove it. When the line of code for the if statement test executes, does it remove the object in the queue?
for (int i = 0; i < waitlist.size(); i++) {
if (waitlist.dequeue() == 3) {
waitlist.dequeue();
}
}
答案1
得分: 0
在if语句
的条件内部的方法调用将会执行,除非条件被短路 -> 当你有一个OR(或者)并且第一个部分已知为真时,第二个部分不会被检查;或者当你有一个AND(并且)并且第一个部分已知为假时,第二个部分不会被检查。
if (true || test()) // test不会被执行
if (false || test()) // test会被执行
if (true && test()) // test会被执行
if (false && test()) // test不会被执行
if (test()) // test会被执行
if (!test()) // test会被执行
这些值也可以是其他方法调用,如下所示:
if (alwaysTrue() || test()) // test永远不会被执行
if (alwaysFalse() || test()) // test会始终被执行
if (alwaysTrue() && test()) // test会始终被执行
if (alwaysFalse() && test()) // test永远不会被执行
基本上,阻止if语句
中的方法调用执行的唯一方法是短路,或者在执行发生之前引发异常。
如果你绝对需要在那里调用一个方法,那么考虑使用没有副作用的方法,比如只是查看值而不从列表中删除它。
ArrayDeque
实现和 LinkedList
实现似乎很适合您的用例。
英文:
The method calls inside the condition of an if-statement
will execute unless the condition is short-circuited -> you have an OR and the first piece is already known to be true, the second piece isn't checked, or you have an AND and the first piece is known to be false, the second piece isn't checked.
if( true || test() ) // test isn't executed
if( false || test()) // test IS executed
if( true && test() ) // test IS executed
if( false && test() )// test isn't executed
if( test() ) // test IS executed
if( !test() )// test IS executed
The values can also be other method calls like so:
if( alwaysTrue() || test() ) // test will never execute
if( alwaysFalse() || test() ) // test will ALWAYS execute
if( alwaysTrue() && test() ) // test will ALWAYS execute
if( alwaysFalse() && test() )// test will never execute
Basically, the only way to prevent a method call in an if-statement
from executing is to short-circuit or cause an exception to be thrown before the execution can happen.
If you absolutely need to call a method there, then consider a method that has no side-effects, such as just peeking at the value instead of removing it from the list.
The ArrayDeque
implementation and the LinkedList
implementation seem like they would fit your use case nicely.
答案2
得分: 0
你所做的是出队并检查结果是否为3,如果是的话,再次出队。实质上,你跳过了下一个元素,如果你想使用它的话。
3后面的任何内容都将被移除;非常简单明了。
在使用大小时要小心,因为在出队项目时它可能会改变。
public class Waitlist {
public static void main(String[] args) {
basicExample(); // 你好,世界,
advancedExample(); // 2,4,6,8,
exceptionExample(); // 成功!
}
// 由于移除了一个项目,因此会提前停止,这是不可靠的。
private static void basicExample() {
Queue<String> waitlist = new LinkedListQueue<>();
waitlist.enqueue("你好");
waitlist.enqueue("世界");
System.out.printf("之前:%s%n", waitlist);
System.out.print("期间:");
for (int i = 0; i < waitlist.size(); i++) {
System.out.printf("%s... ", waitlist.dequeue());
}
System.out.printf("%n之后:%s%n%n", waitlist);
}
// 遍历整个队列并移除所有项目,打印偶数。
private static void advancedExample() {
Queue<Integer> waitlist = new LinkedListQueue<>();
for (int i = 0; i < 10; i++) waitlist.enqueue(i);
System.out.printf("之前:%s%n", waitlist);
System.out.print("期间:");
while (!waitlist.isEmpty()) {
if (waitlist.dequeue() % 2 == 1 && !waitlist.isEmpty()) {
System.out.printf("%s... ", waitlist.dequeue());
}
}
System.out.printf("%n之后:%s%n%n", waitlist);
}
// 抛出异常
private static void exceptionExample() {
int max = 8;
Queue<Integer> waitlist = new LinkedListQueue<>(max); // 最多8个
try {
for (int i = 0; i <= max; i++) {
waitlist.enqueue(i);
}
} catch (QueueFullException e) {
System.out.println("成功!"); // 我们达到了容量!
}
}
}
输出
之前:你好,世界
期间:你好...
之后:世界
之前:0,1,2,3,4,5,6,7,8,9
期间:2... 4... 6... 8...
之后:
成功!
LinkedListQueue.java
基于 此处,但我将其设为了抽象。
import java.util.Iterator;
public class LinkedListQueue<T> implements Queue<T> {
private static class Node<E> {
private E data;
private Node<E> next;
public Node(E data) {
this.data = data;
next = null;
}
}
private Node<T> head, tail;
private int size, capacity;
public LinkedListQueue() {
this(Integer.MAX_VALUE);
}
public LinkedListQueue(int capacity) {
this.size = 0;
this.capacity = capacity;
}
@Override
public void setCapacity(int capacity) {
this.capacity = capacity;
}
@Override
public void enqueue(T data) throws QueueFullException {
if (this.size == this.capacity) {
throw new QueueFullException("队列已达到最大容量。");
}
Node<T> node = new Node<>(data);
if (head == null) {
head = node;
} else {
tail.next = node;
}
tail = node;
size++;
}
@Override
public T dequeue() {
if (isEmpty()) {
throw new NullPointerException("此队列没有可出队的项目。");
}
T temp = head.data;
head = head.next;
size--;
return temp;
}
@Override
public boolean isEmpty() {
return head == null;
}
@Override
public int size() {
return size;
}
@Override
public Iterator<T> iterator() {
return new Iterator<T>() {
Node<T> curr = head;
@Override
public boolean hasNext() {
return curr != null;
}
@Override
public T next() {
T data = curr.data;
curr = curr.next;
return data;
}
};
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
Iterator<T> it = this.iterator();
while (it.hasNext()) {
builder.append(it.next() + ", ");
}
return builder.toString().replaceAll(", $", "");
}
}
Queue.java
public interface Queue<T> extends Collection<T> {
void enqueue(T data) throws QueueFullException;
T dequeue();
void setCapacity(int capacity);
}
Collection.java
public interface Collection<T> extends Iterable<T> {
boolean isEmpty();
int size();
}
QueueFullException.java
public class QueueFullException extends RuntimeException {
public QueueFullException() {
super();
}
public QueueFullException(String message) {
super(message);
}
}
英文:
What you are doing is de-queuing and checking if the result is 3, if so, de-queue again. You are essentially skipping the next one, if you wanted to use it.
Whatever came after 3, will be removed; plain and simple.
Be careful about using the size, at this can change as you are de-queuing items.
public class Waitlist {
public static void main(String[] args) {
basicExample(); // Hello, World,
advancedExample(); // 2, 4, 6, 8,
exceptionExample(); // Success!
}
// Stops short, because one item was removed, this is unreliable.
private static void basicExample() {
Queue<String> waitlist = new LinkedListQueue<>();
waitlist.enequeue("Hello");
waitlist.enequeue("World");
System.out.printf("Before : %s%n", waitlist);
System.out.print("During : ");
for (int i = 0; i < waitlist.size(); i++) {
System.out.printf("%s... ", waitlist.dequeue());
}
System.out.printf("%nAfter : %s%n%n", waitlist);
}
// Runs through the entire queue and removes, all items, printing even numbers.
private static void advancedExample() {
Queue<Integer> waitlist = new LinkedListQueue<>();
for (int i = 0; i < 10; i++) waitlist.enequeue(i);
System.out.printf("Before : %s%n", waitlist);
System.out.print("During : ");
while (!waitlist.isEmpty()) {
if (waitlist.dequeue() % 2 == 1 && !waitlist.isEmpty()) {
System.out.printf("%s... ", waitlist.dequeue());
}
}
System.out.printf("%nAfter : %s%n%n", waitlist);
}
// Throws an exception
private static void exceptionExample() {
int max = 8;
Queue<Integer> waitlist = new LinkedListQueue<>(max); // max of 8
try {
for (int i = 0; i <= max; i++) {
waitlist.enequeue(i);
}
} catch (QueueFullException e) {
System.out.println("Success!"); // We reached capacity!
}
}
}
Output
Before : Hello, World
During : Hello...
After : World
Before : 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
During : 2... 4... 6... 8...
After :
Success!
LinkedListQueue.java
Based on this, but I made it abstract.
import java.util.Iterator;
public class LinkedListQueue<T> implements Queue<T> {
private static class Node<E> {
private E data;
private Node<E> next;
public Node(E data) {
this.data = data;
next = null;
}
}
private Node<T> head, tail;
private int size, capacity;
public LinkedListQueue() {
this(Integer.MAX_VALUE);
}
public LinkedListQueue(int capacity) {
this.size = 0;
this.capacity = capacity;
}
@Override
public void setCapacity(int capacity) {
this.capacity = capacity;
}
@Override
public void enequeue(T data) throws QueueFullException {
if (this.size == this.capacity) {
throw new QueueFullException("The queue has reached its maximum capacity.");
}
Node<T> node = new Node<>(data);
if (head == null) {
head = node;
} else {
tail.next = node;
}
tail = node;
size++;
}
@Override
public T dequeue() {
if (isEmpty()) {
throw new NullPointerException("There is nothing to dequeue from this queue.");
}
T temp = head.data;
head = head.next;
size--;
return temp;
}
@Override
public boolean isEmpty() {
return head == null;
}
@Override
public int size() {
return size;
}
@Override
public Iterator<T> iterator() {
return new Iterator<T>() {
Node<T> curr = head;
@Override
public boolean hasNext() {
return curr != null;
}
@Override
public T next() {
T data = curr.data;
curr = curr.next;
return data;
}
};
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
Iterator<T> it = this.iterator();
while (it.hasNext()) {
builder.append(it.next() + ", ");
}
return builder.toString().replaceAll(", $", "");
}
}
Queue.java
public interface Queue<T> extends Collection<T> {
void enequeue(T data) throws QueueFullException;
T dequeue();
void setCapacity(int capacity);
}
Collection.java
public interface Collection<T> extends Iterable<T> {
boolean isEmpty();
int size();
}
QueueFullException.java
public class QueueFullException extends RuntimeException {
public QueueFullException() {
super();
}
public QueueFullException(String message) {
super(message);
}
}
专注分享java语言的经验与见解,让所有开发者获益!
评论