简体   繁体   English

使用ArrayList的IndexOutOfBoundsException

[英]IndexOutOfBoundsException using ArrayList

I have a option for the user to pick a Month. 用户可以选择一个月。 I set a listener ItemListener for my ComboBox which contains list of Months. 我为包含月份列表的ComboBox设置了一个侦听器ItemListener I have a set condition where if the user pick "February" list of days will only up to 29 else "April","June" and so on will have 30 days on my ComboBox. 我有一个设定的条件,如果用户选择“二月”的天列表,最多只能有29天, “四月”,“六月” ,依此类推,则ComboBox上将有30天。 But when I choose "February" it works fine but when I select another month I get an error. 但是,当我选择“ 2月”时,它可以正常工作,但是当我选择另一个月时,我会收到一个错误消息。

IndexOutOfBoundsException: Index: 30, Size: 29

I know this error occur because the another month has a Index of 30. I'm little bit confuse should I remove the content of ArrayList or the ComboBox? 我知道发生此错误是因为另一个月份的索引为30。我有点困惑,应该删除ArrayList或ComboBox的内容吗? Any help how can I eliminate this? 有什么帮助我该如何消除呢?

private ItemHandler handler = new ItemHandler();

ArrayList<String> daysList = new ArrayList<String>();

String[] daysObj = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15",
        "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31"};
 DefaultComboBoxModel daysModel = new DefaultComboBoxModel(daysObj);

public AddEmployee() 
{
  setMonths();
  setDays();
  cbMonths.addItemListener(handler);
}

private void setDays()
{   
    for(int i = 0; i < daysObj.length; i++)
    {
        daysList.add(daysObj[i]);
    }

    cbDays.setModel((ComboBoxModel)daysModel);   
}

private class ItemHandler implements ItemListener
{
    int removeDays[] = {29,30};//array
    int remove[] = {30};
    @Override
    public void itemStateChanged(ItemEvent e) 
    {
        if(e.getSource() == cbMonths)//Check where combobox occured.
        {
            if(cbMonths.getSelectedItem().equals("February"))
            {
                for(int i = removeDays.length-1; i >= 0; i--)
                {
                    daysList.remove(removeDays[i]);//Remove given array from ArrayList using removeDays[]
                    System.out.println("NEW ELEMENT: "+daysList);
                }

                for(String s : daysList)//Update ArrayList
                {
                    cbDays.addItem(s);
                    System.out.println("NEW LIST OF ARRAY: "+s);
                }

            }
            else if(cbMonths.getSelectedItem().equals("April") || cbMonths.getSelectedItem().equals("June") || 
                    cbMonths.getSelectedItem().equals("September") || cbMonths.getSelectedItem().equals("November"))
            {
                for(int i = remove.length-1; i >= 0; i--)
                {
                    daysList.remove(remove[i]);
                    System.out.println(daysList);
                }

                for(String a : daysList)//Update ArrayList
                {
                    cbDays.addItem(a);
                    System.out.println("NEW LIST OF ARRAY: "+a);
                }

            }
      }
}

I tried a method removeAllItems() but it look likes it doesn't work. 我尝试了方法removeAllItems()但它似乎不起作用。 cbDays.removeAllItems();

Instead of doing complex calculations each time a user chooses another month (which is hard to read and error prone), better initialize some static models which cover all cases. 与其每次用户选择另一个月(这很难读取且容易出错),都执行复杂的计算,而是更好地初始化一些涵盖所有情况的静态模型。 Your StateChaged handler then only has to pick the correct model. 然后,您的StateChaged处理程序只需选择正确的模型。 Following example is based on the new fancy java 8 datetime API: 下面的示例基于新的java 8 datetime API:

private static String[] initDays( int number )
{
    String[] result = new String[ number];

    for ( int i = 0; i < result.length; i++ )
    {
        result[i] = "" + ( i+1);
    }

    return result;
}

private static final String[] days28 = initDays( 28);
private static final String[] days29 = initDays( 29);
private static final String[] days30 = initDays( 30);
private static final String[] days31 = initDays( 31);

private static final ComboBoxModel<String> model28 = new DefaultComboBoxModel<>(days28);
private static final ComboBoxModel<String> model29 = new DefaultComboBoxModel<>(days29);
private static final ComboBoxModel<String> model30 = new DefaultComboBoxModel<>(days30);
private static final ComboBoxModel<String> model31 = new DefaultComboBoxModel<>(days31);

private static final Set<Month> month30 = EnumSet.of(
         Month.FEBRUARY,
         Month.APRIL,
         Month.JUNE,
         Month.SEPTEMBER,
         Month.NOVEMBER
     );
private static final Set<Month> month31 = EnumSet.of(
         Month.JANUARY,
         Month.MARCH,
         Month.MAY,
         Month.JULY,
         Month.AUGUST,
         Month.OCTOBER,
         Month.DECEMBER
     );
private JComboBox<String> cbMonths = new JComboBox<>();
private JComboBox<String> cbDays = new JComboBox<>();

public void itemStateChanged(ItemEvent e)
{
    if(e.getSource() == cbMonths)//Check where combobox occured.
    {
        if(cbMonths.getSelectedItem().equals("February"))
        {
            Month selectedMonth = Month.valueOf( cbMonths.getItemAt( cbMonths.getSelectedIndex() ) );

            if ( month31.contains( selectedMonth ) )
            {
                cbDays.setModel( model31 );
            }
            else if ( month30.contains( selectedMonth ) )
            {
                cbDays.setModel( model30 );
            }
            else
            {
                if ( Year.isLeap( Instant.now().getLong( ChronoField.YEAR ) ) )
                {
                    cbDays.setModel( model29 );
                }
                else
                {
                    cbDays.setModel( model28 );
                }
            }
        }
    }
}

A further enhancement could be to use a cbMonth which is directly typed by the Month enum, and provide a cell renderer which displays the month in the locale of the user. 进一步的增强可能是使用由Month枚举直接键入的cbMonth,并提供一个单元格渲染器,该渲染器在用户的语言环境中显示月份。

After initialization via setDays() daysList contains 31 elements. 通过setDays()初始化后, daysList包含31个元素。 When February is selected, two elements with the index 29 and 30 are removed: 选择February ,将删除索引为2930两个元素:

    daysList.remove(removeDays[i])

daysList is now having 29 elements. daysList现在有29元素。 When another month is selected, one element with index 30 is removed 选择另一个月后,将删除索引为30一个元素

    daysList.remove(remove[i]);

But dayslist only has 29 elements, so an IndexOutOfBoundsException is thrown. 但是dayslist只有29个元素,因此抛出IndexOutOfBoundsException

Therefore one solution might be to re-initialize daysList everytime itemStateChanged is triggered. 因此,一种解决方案可能是每次触发itemStateChanged重新初始化daysList

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

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