简体   繁体   English

从字符堆栈构造String的有效且简洁的方法是什么?

[英]What is the efficient and concise way to construct a String from Character Stack

Suppose I have a stack - 假设我有一个堆栈 -

O (stack top)
L
L
E
H (stack bottom)

What is the concise way to convert it to "HELLO" 将它转换为“HELLO”的简洁方法是什么?

Now I am doing this way - 现在我这样做 -

private static String getString(Stack<Character> charStack) {
  StringBuilder output = new StringBuilder();

  while (!charStack.isEmpty()) {
      output.append(charStack.pop());    
  }

  return output.reverse().toString();
}

Using map and Collectors , one way of doing what the code in question intend would be: 使用mapCollectors ,一种方法可以执行有问题的代码:

return charStack.stream().map(Object::toString).collect(Collectors.joining());

Edit : As visible from comments (1) and (2) , if emptying the stack is an intentional action, you can update the code to include the behaviour as follows: 编辑 :从注释(1)(2)可见,如果清空堆栈是一个有意的操作,您可以更新代码以包括行为,如下所示:

String output = charStack.stream().map(Object::toString).collect(Collectors.joining());
charStack.clear();
return output;

Note 注意

I accidentally thought you are searching for a faster version . 我不小心以为你在寻找更快的版本 However I decided to leave the discussion here as it could be useful for future readers. 但是我决定离开这里的讨论,因为它可能对未来的读者有用。


Analysis 分析

You can not achieve a better version with the given input, at least when talking about complexity classes. 至少在谈论复杂性类时,您无法使用给定的输入实现更好的版本。 Your Stack can only be traversed from last to first item, not in the correct order for a String . 您的Stack只能从最后一个项目遍历到第一个项目,而不能按String正确顺序遍历。

You can not directly use the knowledge that your final String needs to be reversed first. 您不能直接使用首先需要反转最终String的知识。

Let's take a look at your code, let's denote by n the size of your stack: 让我们来看看你的代码,让我们表示n您的堆栈的大小:

private static String getString(Stack<Character> charStack) {
    StringBuilder output = new StringBuilder();

    // Yields n iterations
    while (!charStack.isEmpty()) {
        output.append(charStack.pop());    
    }

    // reverse creates n iterations
    // toString creates n iterations
    return output.reverse().toString();
}

In total we have 3 * n iterations yielding O(n) . 总共我们有3 * n次迭代产生O(n)


Size known 尺寸已知

If you know the size of the stack you could experiment with arrays ( Stack has no size method). 如果你知道堆栈的大小 ,你可以试验数组( Stack没有size方法)。 The advantage of them is that they can be traversed and edited in any direction at no additional cost. 它们的优点是可以在任何方向上遍历和编辑它们而无需额外费用。 Take a look at the following example: 看一下下面的例子:

int size = ...
char[] textChars = new char[size];

// Yields n iterations
for (int i = 0; i < size; i++) {
    // Reversely set the array
    // Setting is done in constant time
    textChars[size - i - 1] = charStack.pop();
}

// Convert the textChars to String
// without using reverse methods
// Yields n iterations
String text = String.valueOf(textChars);

In total we have 2 * n iterations, also yielding O(n) . 总共我们有2 * n次迭代,也产生O(n)

So it might indeed be slightly faster, provided you know the size . 如果您知道尺寸 ,它可能确实会稍快一些。 However the difference will not be that big, its O(n) too. 然而,差异不会那么大,它的O(n)也是如此。


Size unknown 大小未知

If you don't know the size you could exchange char[] with ArrayList<Character> ( LinkedList would also work, but could be slower): 如果您不知道大小,可以使用ArrayList<Character>交换char[]LinkedList也可以,但可能会更慢):

ArrayList<Character> textChars = new ArrayList<>();

// Yields n iterations
for (char c : charStack) {
    // Set the ArrayList
    // Setting is done in constant time
    textChars.add(charStack.pop());
}

// Unfortunately there is no nice method
// to directly convert ArrayList to String
StringBuilder sb = new StringBuilder();

// Reversely iterate the ArrayList, the reverse
// direction comes at no additional cost
// Yields n iterations
for (int i = textChars.size() - 1; i >= 0; i--) {
    sb.append(textChars.get(i));
}

// Yields n iterations
String text = sb.toString();

Now we have about 3 * n iterations but with a bigger overhead due to ArrayList and Character . 现在我们有大约3 * n次迭代但由于ArrayListCharacter而导致更大的开销。 Without having made experiments I would say that your approach is better than any kind of this, if the size is unknown. 如果没有进行实验,我会说如果尺寸未知,你的方法比任何一种都好。

Note that charStack.pop() actually removes the elements from the stack - are you sure that it is intended? 请注意, charStack.pop()实际上从堆栈中删除了元素 - 你确定它是有意的吗?

You could do it like that without removing elements: 你可以这样做而不删除元素:

private static String getString(Stack<Character> charStack) {
    StringBuilder output = new StringBuilder();

    for (Character c : charStack) {
        output.append(c);    
    }

    return output.reverse().toString();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM