将字符串转换为地图列表

时间:2020-04-08 14:10:51

标签: java collections java-8 java-stream

我有一个以下字符串。我想将其转换为地图列表,如下所示,

import React from 'react';
import {Link, withRouter} from 'react-router-dom';
import Button from '@material-ui/core/Button';

class Quiz extends React.Component {
    constructor(props) {
        super(props)

        this.state = {current:0, level: props.level, dataSet:props.data, correct:0, incorrect:0}
        this.handleClick = this.handleClick.bind(this)

    }

    handleClick(choice) {
        if (choice === this.state.dataSet[this.state.current].correct) {
          this.setState({correct: this.state.correct + 1})
        } else {
          this.setState({incorrect: this.state.incorrect + 1})
        }

        if (this.state.current === 4) { 
            if(this.state.correct + this.state.incorrect === 4){ 
                this.setState({current: this.state.current}) 
            }
            else {
                this.setState({current: 0})
                this.setState({incorrect: 0})
                this.setState({correct: 0})
            }
        } else {
             this.setState({current: this.state.current + 1}) 
        }
      }

      render() { 
        var style = {
            width: "25%",
            display: "block",
            backgroundColor: "green",
            textAlign: "center",
            color: "white"
          }
        if(this.state.current === 4 && this.state.correct === 5 ){
            var l = this.state.level + 1
            var next = '/level' + l
            return(
                <div>
                    <ScoreArea correct={this.state.correct} incorrect={this.state.incorrect} />
                    <h3 align="left">Passaste de nível!</h3>
                    <Button style={style} component={Link} to={next}>
                        Next Level
                    </Button>
                </div>
            )
        } 
        else {
            return(
                <div>
                  <ScoreArea correct={this.state.correct} incorrect={this.state.incorrect} />
                  <QuizArea handleClick={this.handleClick} dataSet={this.state.dataSet[this.state.current]} />
                </div>
              )
        }        
      }
}

....

export default withRouter(Quiz);

输出:

String esConnectionPropertiesStr = "ID1, 701, REST, 0, $PROJECT_ID),\n" +
               "ID2, 702, ES_USERNAME, 0, $PROJECT_ID),\n" +
               "ID3, 703, ES_PASSWORD, 0, $PROJECT_ID),\n" +
               "ID4, 704, ES_HOST, 0, $PROJECT_ID";

先用[ {1=ID1, 2=701, 3= ES_USERNAME, 4= 0, 5= $PROJECT_ID}, {1=ID2, 2=702, 3= ES_PASSWORD, 4= 0, 5= $PROJECT_ID}, {1=ID3, 2=703, 3=ES_HOST, 4= 0, 5= $PROJECT_ID}, {1=ID4, 2=704, 3= ES_PORT, 4= 0, 5=$PROJECT_ID} ] 分割,然后用逗号分割以获取地图元素。我尝试了以下方法,

),

还有什么更好的方法吗?

1 个答案:

答案 0 :(得分:1)

AtomicInteger在这里是多余的。它增加了更多的复杂性和更多的失败空间。 此外,Stream API does not guarantee的规范是Stream::peek的执行。

这是幼稚的(虽然很长)解决方案:

List<Map<Integer, String>> resultMap =
        Arrays.stream(esConnectionPropertiesStr.split("\\),"))
              .map(row -> Arrays.stream(row.split(","))
                                .collect(collectingAndThen(toList(), 
                                         list ->IntStream.range(0, list.size())
                                                         .boxed()
                                                         .collect(toMap(identity(), list::get)))))
              .collect(toList());

尽管上述解决方案有效,但恕我直言,它不可读。我会将list-to-map转换提取为静态util方法:

class Utils { // 
    public static Map<Integer, String> toIndexedMap(List<String> list) {
        return IntStream.range(0, list.size())
                        .boxed()
                        .collect(toMap(identity(), list::get));
}

然后使用以下实用方法:

List<Map<Integer, String>> result =
        Arrays.stream(esConnectionPropertiesStr.split("\\),"))
              .map(row -> Arrays.stream(row.split(","))
                                .collect(collectingAndThen(toList(), Utils::toIndexedMap)))
              .collect(toList());