java - किसी सूची से तत्व को निकालने का प्रयास करते समय मुझे असमर्थित ऑपरेशन अपवाद क्यों मिलता है?




exception list (8)

Arrays से कोड का स्निपेट निम्नलिखित है

public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }

    /**
     * @serial include
     */
    private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable
    {
        private static final long serialVersionUID = -2764017481108945198L;
        private final E[] a;

तो क्या होता है कि जब लिस्ट विधि कहा जाता है तो यह अपने निजी स्थैतिक वर्ग संस्करण की सूची देता है जो सरणी में तत्व तत्व को स्टोर करने के लिए सारसूची से जोड़ें funcion को ओवरराइड नहीं करता है। तो डिफ़ॉल्ट रूप से सार सूची में विधि जोड़ें अपवाद फेंकता है।

तो यह नियमित सरणी सूची नहीं है।

मेरे पास यह कोड है:

public static String SelectRandomFromTemplate(String template,int count) {
   String[] split = template.split("|");
   List<String> list=Arrays.asList(split);
   Random r = new Random();
   while( list.size() > count ) {
      list.remove(r.nextInt(list.size()));
   }
   return StringUtils.join(list, ", ");
}

मैंने इसे प्राप्त किया:

06-03 15:05:29.614: ERROR/AndroidRuntime(7737): java.lang.UnsupportedOperationException
06-03 15:05:29.614: ERROR/AndroidRuntime(7737):     at java.util.AbstractList.remove(AbstractList.java:645)

यह सही तरीका कैसे होगा? Java.15


Arrays.asList () एक ऐसी सूची देता है जो संचालन को अपने आकार को प्रभावित करने की अनुमति नहीं देता है (ध्यान दें कि यह "अप्रचलित" जैसा नहीं है)।

आप new ArrayList<String>(Arrays.asList(split)); एक वास्तविक प्रतिलिपि बनाने के लिए, लेकिन जो आप करने की कोशिश कर रहे हैं उसे देखते हुए, यहां एक अतिरिक्त सुझाव है (आपके पास नीचे एक O(n^2) एल्गोरिदम है)।

आप list.size() - count को हटाना चाहते हैं list.size() - count (इस के कॉल को याद रखें) सूची से यादृच्छिक तत्व। बस कई यादृच्छिक तत्वों को चुनें और उन्हें सूची के अंत k पदों पर स्वैप करें, फिर उस संपूर्ण सीमा को हटाएं (उदाहरण के लिए उपसूची () और स्पष्ट () का उपयोग करना)। यह इसे दुबला कर देगा और मतलब O(n) एल्गोरिदम ( O(k) अधिक सटीक है)।

अद्यतन : जैसा कि नीचे बताया गया है, यह एल्गोरिदम केवल तभी समझ में आता है जब तत्व अनियंत्रित होते हैं, उदाहरण के लिए यदि सूची एक बैग का प्रतिनिधित्व करती है। यदि, दूसरी ओर, सूची का एक सार्थक आदेश है, तो यह एल्गोरिदम इसे संरक्षित नहीं करेगा (इसके बजाय पॉलीजेनेलब्रिकेंट्स एल्गोरिदम) होगा।

अद्यतन 2 : तो पीछे की ओर, एक बेहतर (रैखिक, बनाए रखने का क्रम, लेकिन ओ (एन) यादृच्छिक संख्या के साथ) एल्गोरिदम कुछ ऐसा होगा:

LinkedList<String> elements = ...; //to avoid the slow ArrayList.remove()
int k = elements.size() - count; //elements to select/delete
int remaining = elements.size(); //elements remaining to be iterated
for (Iterator i = elements.iterator(); k > 0 && i.hasNext(); remaining--) {
  i.next();
  if (random.nextInt(remaining) < k) {
     //or (random.nextDouble() < (double)k/remaining)
     i.remove();
     k--;
  }
}

आप हटा नहीं सकते हैं, न ही आप Arrays की एक निश्चित आकार-सूची में जोड़ सकते हैं।

लेकिन आप उस सूची से अपना उपन्यास बना सकते हैं।

list = list.subList(0, list.size() - (list.size() - count));

public static String SelectRandomFromTemplate(String template, int count) {
   String[] split = template.split("\\|");
   List<String> list = Arrays.asList(split);
   Random r = new Random();
   while( list.size() > count ) {
      list = list.subList(0, list.size() - (list.size() - count));
   }
   return StringUtils.join(list, ", ");
}

* अन्य तरीका है

ArrayList<String> al = new ArrayList<String>(Arrays.asList(template));

यह ArrayList बना देगा जो Arrays.asList जैसे निश्चित आकार नहीं है


आपके कोड के साथ काफी कुछ समस्याएं:

Arrays.asList पर एक निश्चित आकार सूची लौटने पर

एपीआई से:

Arrays.asList : निर्दिष्ट सरणी द्वारा समर्थित एक निश्चित आकार की सूची देता है।

आप इसमें शामिल नहीं कर सकते; आप इससे remove नहीं सकते हैं। आप List को संरचनात्मक रूप से संशोधित नहीं कर सकते हैं।

ठीक कर

एक LinkedList बनाएं, जो तेजी से remove का समर्थन करता है।

List<String> list = new LinkedList<String>(Arrays.asList(split));

split पर रेगेक्स लेना

एपीआई से:

String.split(String regex) : दिए गए नियमित अभिव्यक्ति के मैचों के आस-पास इस स्ट्रिंग को String.split(String regex)

| एक रेगेक्स मेटाएक्टेक्टर है; यदि आप एक शाब्दिक पर विभाजित करना चाहते हैं , आपको इसे \| , जो एक जावा स्ट्रिंग अक्षर के रूप में है "\\|"

ठीक कर:

template.split("\\|")

बेहतर एल्गोरिदम पर

यादृच्छिक सूचकांक के साथ एक समय में एक को remove बजाय, श्रेणी में पर्याप्त यादृच्छिक संख्याएं उत्पन्न करना बेहतर होता है, और उसके बाद एक List listIterator() , उचित सूचकांक पर remove() को कॉल करने के साथ List एक बार listIterator() करना बेहतर होता है। किसी दिए गए सीमा में यादृच्छिक लेकिन विशिष्ट संख्याएं उत्पन्न करने के तरीके पर स्टैक ओवरफ्लो पर प्रश्न हैं।

इसके साथ, आपका एल्गोरिदम O(N)


मुझे उस समस्या के लिए एक और समाधान मिला है:

List<String> list = Arrays.asList(split);
List<String> newList = new ArrayList<>(list);

नई सूची पर काम;)


मुझे लगता है कि बदल रहा है:

List<String> list = Arrays.asList(split);

साथ में

List<String> list = new ArrayList<String>(Arrays.asList(split));

समस्या का समाधान करता है।


शायद क्योंकि आप unmodifiable wrapper के साथ काम कर रहे हैं।

इस लाइन को बदलें:

List<String> list = Arrays.asList(split);

इस लाइन में:

List<String> list = new LinkedList<>(Arrays.asList(split));

हां, Arrays.asList पर, एक निश्चित आकार सूची लौट रहा है।

एक लिंक्ड सूची का उपयोग करने के अलावा, बस addAll विधि सूची का उपयोग करें।

उदाहरण:

String idList = "123,222,333,444";

List<String> parentRecepeIdList = new ArrayList<String>();

parentRecepeIdList.addAll(Arrays.asList(idList.split(","))); 

parentRecepeIdList.add("555");






arraylist