Java Language
संग्रह
खोज…
परिचय
java.util में संग्रह की रूपरेखा कार्यक्षमता के साथ डेटा के सेट के लिए कई सामान्य कक्षाएं प्रदान करती है जो नियमित सरणियों द्वारा प्रदान नहीं की जा सकती हैं।
संग्रह की रूपरेखा में Collection<O> के लिए मुख्य उप-इंटरफ़ेस List<O> और Set<O> साथ इंटरफेस है, और मानचित्र मानचित्र संग्रह Map<K,V> । संग्रह मूल इंटरफ़ेस हैं और कई अन्य संग्रह रूपरेखाओं द्वारा कार्यान्वित किए जा रहे हैं।
टिप्पणियों
संग्रह ऐसी वस्तुएं हैं जो उनके अंदर अन्य वस्तुओं के संग्रह को संग्रहीत कर सकती हैं। आप जेनरिक का उपयोग करके संग्रह में संग्रहीत डेटा का प्रकार निर्दिष्ट कर सकते हैं।
संग्रह आमतौर पर java.util या java.util.concurrent नामस्थान का उपयोग करते हैं।
जावा 1.4.2 और नीचे जेनरिक का समर्थन नहीं करते हैं। जैसे, आप उस प्रकार के पैरामीटर को निर्दिष्ट नहीं कर सकते हैं जिसमें एक संग्रह होता है। प्रकार की सुरक्षा नहीं होने के अलावा, आपको संग्रह से सही प्रकार को वापस लाने के लिए भी कलाकारों का उपयोग करना चाहिए।
Collection<E> अलावा, कई प्रमुख प्रकार के संग्रह हैं, जिनमें से कुछ उपप्रकार हैं।
-
List<E>वस्तुओं का एक आदेश दिया संग्रह है। यह एक सरणी के समान है, लेकिन एक आकार सीमा को परिभाषित नहीं करता है। कार्यान्वयन आमतौर पर नए तत्वों को समायोजित करने के लिए आंतरिक रूप से आकार में बढ़ेगा। -
Set<E>वस्तुओं का एक संग्रह है जो डुप्लिकेट की अनुमति नहीं देता है।-
SortedSet<E>एकSet<E>जो तत्व आदेश को भी निर्दिष्ट करता है।
-
-
Map<K,V>कुंजी / मूल्य जोड़े का एक संग्रह है।-
SortedMap<K,V>एकMap<K,V>जो तत्व आदेश को भी निर्दिष्ट करता है।
-
जावा 5 एक नए संग्रह प्रकार में जोड़ता है:
-
Queue<E>एक विशिष्ट क्रम में संसाधित होने वाले तत्वों का एक संग्रह है। कार्यान्वयन निर्दिष्ट करता है कि क्या यह फीफो या एलआईएफओ है। यहStackवर्ग का पालन करता है।
जावा 6 संग्रह के कुछ नए उपप्रकारों में जोड़ता है।
-
NavigableSet<E>एकSet<E>जिसमें विशेष नेविगेशन विधियों का निर्माण किया गया है। -
NavigableMap<K,V>एकMap<K,V>जिसमें विशेष नेविगेशन विधियों का निर्माण किया गया है। -
Deque<E>एकQueue<E>जिसे या तो अंत से पढ़ा जा सकता है।
ध्यान दें कि उपरोक्त आइटम सभी इंटरफेस हैं। उनका उपयोग करने के लिए, आपको उपयुक्त क्रियान्वयन कक्षाएं, जैसे कि ArrayList , HashSet , HashMap या PriorityQueue HashMap ।
प्रत्येक प्रकार के संग्रह में कई कार्यान्वयन हैं जिनमें विभिन्न प्रदर्शन मीट्रिक और उपयोग के मामले हैं।
ध्यान दें कि Liskov प्रतिस्थापन सिद्धांत संग्रह उपप्रकारों पर लागू होता है। यह है, एक SortedSet<E> Set<E> अपेक्षा कर एक फ़ंक्शन को पास किया जा सकता है। क्लास इनहेरिटेंस के साथ संग्रह का उपयोग कैसे करें के बारे में अधिक जानकारी के लिए जेनरिक सेक्शन में बाउंडेड पैरामीटर्स के बारे में पढ़ना उपयोगी है।
यदि आप अपने स्वयं के संग्रह बनाना चाहते हैं, तो इंटरफ़ेस को लागू करने के बजाय अमूर्त वर्गों (जैसे कि AbstractList ) में से एक को विरासत में लेना आसान हो सकता है।
1.2 से पहले, आपको इसके बजाय निम्नलिखित वर्गों / इंटरफेस का उपयोग करना होगा:
-
ArrayListबजायVector -
MapबजायDictionary। ध्यान दें कि एक इंटरफ़ेस के बजाय शब्दकोश एक सार वर्ग भी है। -
HashtableबजायHashMap
ये कक्षाएं अप्रचलित हैं और इन्हें आधुनिक कोड में उपयोग नहीं किया जाना चाहिए।
एक ArrayList की घोषणा और वस्तुओं को जोड़ने
हम एक ArrayList ( List अंतरफलक के बाद) बना सकते हैं:
List aListOfFruits = new ArrayList();
List<String> aListOfFruits = new ArrayList<String>();
List<String> aListOfFruits = new ArrayList<>();
अब, String add लिए विधि add का उपयोग करें:
aListOfFruits.add("Melon");
aListOfFruits.add("Strawberry");
उपर्युक्त उदाहरण में, ArrayList में 0 पर String "तरबूज" और 1 पर String "Strawberry" शामिल होगी।
इसके अलावा, हम addAll(Collection<? extends E> c) विधि के साथ कई तत्वों को जोड़ सकते हैं
List<String> aListOfFruitsAndVeggies = new ArrayList<String>();
aListOfFruitsAndVeggies.add("Onion");
aListOfFruitsAndVeggies.addAll(aListOfFruits);
अब "प्याज" को aListOfFruitsAndVeggies में 0 इंडेक्स पर रखा गया है, "मेलन" इंडेक्स 1 में है और "स्ट्रॉबेरी" इंडेक्स 2 पर है।
मौजूदा डेटा से संग्रह का निर्माण
मानक संग्रह
जावा संग्रह रूपरेखा
एक निर्माण करने के लिए एक आसान तरीका List अलग-अलग डेटा मूल्यों से उपयोग करने के लिए है java.utils.Arrays विधि Arrays.asList :
List<String> data = Arrays.asList("ab", "bc", "cd", "ab", "bc", "cd");
सभी मानक संग्रह कार्यान्वयन निर्माणकर्ता प्रदान करते हैं जो निर्माण के समय नए संग्रह में सभी तत्वों को जोड़ने वाले तर्क के रूप में एक और संग्रह लेते हैं:
List<String> list = new ArrayList<>(data); // will add data as is
Set<String> set1 = new HashSet<>(data); // will add data keeping only unique values
SortedSet<String> set2 = new TreeSet<>(data); // will add data keeping unique values and sorting
Set<String> set3 = new LinkedHashSet<>(data); // will add data keeping only unique values and preserving the original order
Google अमरूद संग्रह रूपरेखा
एक अन्य महान रूपरेखा Google Guava जो विभिन्न प्रकार के मानक संग्रह Lists और Sets के निर्माण के लिए अद्भुत उपयोगिता वर्ग (सुविधा स्थैतिक तरीके प्रदान करना) है:
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
...
List<String> list1 = Lists.newArrayList("ab", "bc", "cd");
List<String> list2 = Lists.newArrayList(data);
Set<String> set4 = Sets.newHashSet(data);
SortedSet<String> set5 = Sets.newTreeSet("bc", "cd", "ab", "bc", "cd");
मानचित्रण संग्रह
जावा संग्रह रूपरेखा
इसी तरह नक्शों के लिए, एक Map<String, Object> map एक नया नक्शा सभी तत्वों के साथ निर्मित किया जा सकता है:
Map<String, Object> map1 = new HashMap<>(map);
SortedMap<String, Object> map2 = new TreeMap<>(map);
अपाचे कॉमन्स कलेक्शंस फ्रेमवर्क
का उपयोग करते हुए Apache Commons आप में सरणी का उपयोग कर मानचित्र बना सकते हैं ArrayUtils.toMap के साथ-साथ MapUtils.toMap :
import org.apache.commons.lang3.ArrayUtils;
...
// Taken from org.apache.commons.lang.ArrayUtils#toMap JavaDoc
// Create a Map mapping colors.
Map colorMap = MapUtils.toMap(new String[][] {{
{"RED", "#FF0000"},
{"GREEN", "#00FF00"},
{"BLUE", "#0000FF"}});
सरणी का प्रत्येक तत्व या तो एक Map.Entry या Array होना चाहिए, जिसमें कम से कम दो तत्व शामिल हों, जहाँ पहले तत्व को कुंजी के रूप में और दूसरे को मान के रूप में उपयोग किया जाता है।
Google अमरूद संग्रह रूपरेखा
Google Guava ढांचे से उपयोगिता वर्ग का नाम Maps :
import com.google.common.collect.Maps;
...
void howToCreateMapsMethod(Function<? super K,V> valueFunction,
Iterable<K> keys1,
Set<K> keys2,
SortedSet<K> keys3) {
ImmutableMap<K, V> map1 = toMap(keys1, valueFunction); // Immutable copy
Map<K, V> map2 = asMap(keys2, valueFunction); // Live Map view
SortedMap<K, V> map3 = toMap(keys3, valueFunction); // Live Map view
}
Stream का उपयोग करना,
Stream.of("xyz", "abc").collect(Collectors.toList());
या
Arrays.stream("xyz", "abc").collect(Collectors.toList());
सूचियों में शामिल हों
स्रोत सूची को संशोधित किए बिना सूचियों में शामिल होने के लिए निम्नलिखित तरीकों का उपयोग किया जा सकता है।
पहले दृष्टिकोण। अधिक रेखाएँ हैं लेकिन समझने में आसान है
List<String> newList = new ArrayList<String>();
newList.addAll(listOne);
newList.addAll(listTwo);
दूसरा तरीका। एक कम लाइन है, लेकिन कम पठनीय है।
List<String> newList = new ArrayList<String>(listOne);
newList.addAll(listTwo);
तीसरा तरीका। तृतीय पक्ष अपाचे कॉमन्स-संग्रह पुस्तकालय की आवश्यकता है।
ListUtils.union(listOne,listTwo);
धाराओं का उपयोग करके उसी को प्राप्त किया जा सकता है
List<String> newList = Stream.concat(listOne.stream(), listTwo.stream()).collect(Collectors.toList());
संदर्भ। इंटरफ़ेस सूची
एक लूप के भीतर सूची से आइटम निकालना
लूप के भीतर सूची से आइटम निकालना मुश्किल है, यह इस तथ्य के कारण है कि सूची का सूचकांक और लंबाई बदल जाती है।
निम्नलिखित सूची को देखते हुए, यहां कुछ उदाहरण दिए गए हैं जो अप्रत्याशित परिणाम देंगे और कुछ ऐसे हैं जो सही परिणाम देंगे।
List<String> fruits = new ArrayList<String>();
fruits.add("Apple");
fruits.add("Banana");
fruits.add("Strawberry");
गलत
बयान "केले" के for पुनरावृत्ति को हटाना :
कोड का नमूना केवल Apple और Strawberry प्रिंट करेगा। Banana को छोड़ दिया जाता है क्योंकि यह Apple के डिलीट होते ही इंडेक्स 0 जाता है, लेकिन उसी समय i 1 हो जाता है।
for (int i = 0; i < fruits.size(); i++) {
System.out.println (fruits.get(i));
if ("Apple".equals(fruits.get(i))) {
fruits.remove(i);
}
}
बढ़ाया में निकाला जा रहा है for बयान फेंकता अपवाद:
क्योंकि एक ही समय में संग्रह पर पुनरावृति और इसे संशोधित करना।
फेंकता है: java.util.ConcurrentModificationException
for (String fruit : fruits) {
System.out.println(fruit);
if ("Apple".equals(fruit)) {
fruits.remove(fruit);
}
}
सही बात
Iterator का उपयोग करते हुए लूप में निकालना
Iterator<String> fruitIterator = fruits.iterator();
while(fruitIterator.hasNext()) {
String fruit = fruitIterator.next();
System.out.println(fruit);
if ("Apple".equals(fruit)) {
fruitIterator.remove();
}
}
Iterator इंटरफ़ेस में इस मामले के लिए केवल एक Iterator remove() विधि है। हालाँकि, इस विधि को दस्तावेज़ में "वैकल्पिक" के रूप में चिह्नित किया गया है, और यह एक UnsupportedOperationException को फेंक सकता है।
फेंकता है: UnsupportedOperationException - यदि निकालने का ऑपरेशन इस पुनरावृत्ति द्वारा समर्थित नहीं है
इसलिए, यह सुनिश्चित करने के लिए प्रलेखन की जांच करने की सलाह दी जाती है कि यह ऑपरेशन समर्थित है (व्यवहार में, जब तक कि संग्रह एक 3 पार्टी लाइब्रेरी के माध्यम से प्राप्त एक अपरिवर्तनीय नहीं है या Collections.unmodifiable...() से एक का उपयोग नहीं करता है Collections.unmodifiable...() विधि, ऑपरेशन लगभग हमेशा समर्थित है)।
Iterator का उपयोग करते समय एक ConcurrentModificationException modCount को फेंक दिया जाता है जब List का modCount बदल दिया जाता है जब Iterator बनाया गया था। यह एक ही थ्रेड या एक ही सूची को साझा करने वाले बहु-थ्रेडेड अनुप्रयोग में हो सकता था।
एक modCount एक है int चर जो कई बार इस सूची संरचनात्मक रूप से संशोधित किया गया है की संख्या की गणना। एक संरचनात्मक परिवर्तन अनिवार्य रूप से Collection वस्तु पर एक add() या remove() ऑपरेशन का आह्वान किया जा रहा है ( Iterator द्वारा किए गए परिवर्तन गिने नहीं जाते हैं)। जब Iterator बनाया जाता है, तो वह इस modCount संग्रहीत करता है और List प्रत्येक पुनरावृत्ति पर जाँच करता है कि क्या वर्तमान modCount समान है और Iterator कब बनाया गया था। यदि modCount मान में कोई परिवर्तन होता है, तो यह एक ConcurrentModificationException modCount फेंकता है।
इसलिए उपर्युक्त सूची के लिए, नीचे जैसा ऑपरेशन किसी अपवाद को नहीं फेंकेगा:
Iterator<String> fruitIterator = fruits.iterator();
fruits.set(0, "Watermelon");
while(fruitIterator.hasNext()){
System.out.println(fruitIterator.next());
}
लेकिन Iterator को इनिशियलाइज़ करने के बाद List एक नया एलिमेंट जोड़ना एक ConcurrentModificationException को फेंक देगा:
Iterator<String> fruitIterator = fruits.iterator();
fruits.add("Watermelon");
while(fruitIterator.hasNext()){
System.out.println(fruitIterator.next()); //ConcurrentModificationException here
}
पीछे की ओर इशारा करते हुए
for (int i = (fruits.size() - 1); i >=0; i--) {
System.out.println (fruits.get(i));
if ("Apple".equals(fruits.get(i))) {
fruits.remove(i);
}
}
यह कुछ भी नहीं छोड़ता है। इस दृष्टिकोण का नकारात्मक पक्ष यह है कि आउटपुट रिवर्स है। हालांकि, ज्यादातर मामलों में जहां आप उन वस्तुओं को हटाते हैं जो मायने नहीं रखेंगे। आपको LinkedList साथ ऐसा कभी नहीं करना चाहिए।
लूप इंडेक्स को एडजस्ट करते हुए आगे की तरफ
for (int i = 0; i < fruits.size(); i++) {
System.out.println (fruits.get(i));
if ("Apple".equals(fruits.get(i))) {
fruits.remove(i);
i--;
}
}
यह कुछ भी नहीं छोड़ता है। जब i वें तत्व को List से हटा दिया जाता है, तो मूल रूप से सूचकांक i+1 पर तैनात तत्व नया i th तत्व बन जाता है। इसलिए, लूप अगले पुनरावृत्ति के लिए अगले तत्व को संसाधित करने के लिए, बिना लंघन के क्रम में i decrement कर सकता है।
"चाहिए-हटाए जाने" की सूची का उपयोग करना
ArrayList shouldBeRemoved = new ArrayList();
for (String str : currentArrayList) {
if (condition) {
shouldBeRemoved.add(str);
}
}
currentArrayList.removeAll(shouldBeRemoved);
यह समाधान डेवलपर को यह जांचने में सक्षम करता है कि क्या सही तत्वों को क्लीनर तरीके से हटा दिया गया है।
जावा 8 में निम्नलिखित विकल्प संभव हैं। ये क्लीनर और अधिक सीधे आगे हैं यदि हटाने को एक लूप में नहीं होना है।
एक फ़िल्टर को फ़िल्टर करना
एक List को स्ट्रीम और फ़िल्टर किया जा सकता है। सभी अवांछित तत्वों को हटाने के लिए एक उचित फिल्टर का उपयोग किया जा सकता है।
List<String> filteredList =
fruits.stream().filter(p -> !"Apple".equals(p)).collect(Collectors.toList());
ध्यान दें कि यहां अन्य सभी उदाहरणों के विपरीत, यह उदाहरण एक नई List उदाहरण का उत्पादन करता है और मूल List अपरिवर्तित रखता है।
removeIf का उपयोग कर removeIf
एक धारा का निर्माण करने के ओवरहेड को बचाता है यदि आवश्यक हो तो सभी मदों का एक समूह निकालना है।
fruits.removeIf(p -> "Apple".equals(p));
अनम्य संग्रह
कभी-कभी यह एक अच्छा अभ्यास नहीं होता है क्योंकि यह एक आंतरिक संग्रह को उजागर करता है क्योंकि यह एक परिवर्तनशील विशेषता के कारण दुर्भावनापूर्ण कोड भेद्यता का कारण बन सकता है। "केवल पढ़ने के लिए" संग्रह प्रदान करने के लिए जावा अपने unmodifiable संस्करणों को प्रदान करता है।
एक संग्रहणीय संग्रह अक्सर एक परिवर्तनीय संग्रह की एक प्रति है जो यह गारंटी देता है कि संग्रह स्वयं को परिवर्तित नहीं किया जा सकता है। इसे संशोधित करने के प्रयासों के परिणामस्वरूप UnsupportedOperationException अपवाद होगा।
यह ध्यान रखना महत्वपूर्ण है कि संग्रह के अंदर मौजूद वस्तुओं को अभी भी बदला जा सकता है।
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class MyPojoClass {
private List<Integer> intList = new ArrayList<>();
public void addValueToIntList(Integer value){
intList.add(value);
}
public List<Integer> getIntList() {
return Collections.unmodifiableList(intList);
}
}
एक अपरिवर्तनीय संग्रह को संशोधित करने का निम्नलिखित प्रयास एक अपवाद फेंक देगा:
import java.util.List;
public class App {
public static void main(String[] args) {
MyPojoClass pojo = new MyPojoClass();
pojo.addValueToIntList(42);
List<Integer> list = pojo.getIntList();
list.add(69);
}
}
उत्पादन:
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableCollection.add(Collections.java:1055)
at App.main(App.java:12)
कलेक्शंस पर जोर देना
सूची में परिवर्तन
List<String> names = new ArrayList<>(Arrays.asList("Clementine", "Duran", "Mike"));
names.forEach(System.out::println);
अगर हमें समानता के उपयोग की आवश्यकता है
names.parallelStream().forEach(System.out::println);
for (String name : names) {
System.out.println(name);
}
for (int i = 0; i < names.size(); i++) {
System.out.println(names.get(i));
}
//Creates ListIterator which supports both forward as well as backward traversel
ListIterator<String> listIterator = names.listIterator();
//Iterates list in forward direction
while(listIterator.hasNext()){
System.out.println(listIterator.next());
}
//Iterates list in backward direction once reaches the last element from above iterator in forward direction
while(listIterator.hasPrevious()){
System.out.println(listIterator.previous());
}
सेट पर छंटनी
Set<String> names = new HashSet<>(Arrays.asList("Clementine", "Duran", "Mike"));
names.forEach(System.out::println);
for (Iterator<String> iterator = names.iterator(); iterator.hasNext(); ) {
System.out.println(iterator.next());
}
for (String name : names) {
System.out.println(name);
}
Iterator iterator = names.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
मानचित्र पर Iterating
Map<Integer, String> names = new HashMap<>();
names.put(1, "Clementine");
names.put(2, "Duran");
names.put(3, "Mike");
names.forEach((key, value) -> System.out.println("Key: " + key + " Value: " + value));
for (Map.Entry<Integer, String> entry : names.entrySet()) {
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
// Iterating over only keys
for (Integer key : names.keySet()) {
System.out.println(key);
}
// Iterating over only values
for (String value : names.values()) {
System.out.println(value);
}
Iterator entries = names.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry entry = (Map.Entry) entries.next();
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
अपरिवर्तनीय खाली संग्रह
कभी-कभी एक अपरिवर्तनीय खाली संग्रह का उपयोग करना उचित होता है। Collections वर्ग इस तरह के संग्रह को एक कुशल तरीके से प्राप्त करने के लिए तरीके प्रदान करता है:
List<String> anEmptyList = Collections.emptyList();
Map<Integer, Date> anEmptyMap = Collections.emptyMap();
Set<Number> anEmptySet = Collections.emptySet();
ये विधियां सामान्य हैं और स्वचालित रूप से दिए गए संग्रह को उस प्रकार में परिवर्तित कर देंगी जिसे इसे सौंपा गया है। यही है, उदाहरण के लिए एक emptyList() को किसी भी प्रकार की List को सौंपा जा सकता है और इसी तरह emptySet() और emptyMap() ।
इन विधियों द्वारा लौटाए गए संग्रह इस बात से अपरिवर्तनीय हैं कि यदि आप उन तरीकों को कॉल करने का प्रयास करते हैं जो उनकी सामग्री ( add , put इत्यादि) को बदल देंगे, तो वे UnsupportedOperationException को फेंक देंगे। ये संग्रह मुख्य रूप से रिक्त विधि के परिणाम या अन्य डिफ़ॉल्ट मानों के विकल्प के रूप में उपयोगी हैं, इसके बजाय null या new वस्तुओं का उपयोग करने के बजाय।
संग्रह और आदिम मूल्य
जावा में संग्रह केवल वस्तुओं के लिए काम करते हैं। यानी जावा में कोई Map<int, int> है। इसके बजाय, आदिम मूल्यों को ऑब्जेक्ट्स में बॉक्सिंग करने की आवश्यकता होती है, जैसा कि Map<Integer, Integer> । जावा ऑटो-बॉक्सिंग इन संग्रहों के पारदर्शी उपयोग को सक्षम करेगा:
Map<Integer, Integer> map = new HashMap<>();
map.put(1, 17); // Automatic boxing of int to Integer objects
int a = map.get(1); // Automatic unboxing.
दुर्भाग्य से, इस का ओवरहेड पर्याप्त है । HashMap<Integer, Integer> को प्रति प्रविष्टि लगभग 72 बाइट्स की आवश्यकता होगी (जैसे कि 64-बिट जेवीएम पर संपीड़ित बिंदुओं के साथ, और पूर्णांकों को 256 से बड़ा मानते हुए, और मानचित्र का 50% भार ग्रहण करना)। क्योंकि वास्तविक डेटा केवल 8 बाइट्स है, यह एक बड़े पैमाने पर ओवरहेड देता है। इसके अलावा, इसे अप्रत्यक्ष के दो स्तर की आवश्यकता होती है (मानचित्र -> प्रवेश -> मूल्य) यह अनावश्यक रूप से धीमा है।
आदिम डेटा प्रकारों के लिए अनुकूलित संग्रह के साथ कई पुस्तकालय मौजूद हैं (जिसमें 50% लोड पर प्रति प्रविष्टि केवल 16 बाइट्स की आवश्यकता होती है, अर्थात 4x कम मेमोरी, और एक स्तर अप्रत्यक्ष कम), जो कि आदिम के बड़े संग्रह का उपयोग करते समय पर्याप्त प्रदर्शन लाभ प्राप्त कर सकते हैं। जावा में मान।
Iterator का उपयोग करके सूचियों से मेल खाने वाली वस्तुओं को हटाना।
ऊपर मैंने एक लूप के भीतर एक सूची से आइटम को हटाने के लिए एक उदाहरण देखा और मैंने एक और उदाहरण के बारे में सोचा जो इस बार Iterator इंटरफ़ेस का उपयोग करके काम में आ सकता है।
यह एक ट्रिक का प्रदर्शन है, जो उन सूचियों में डुप्लिकेट आइटम से निपटने के दौरान काम आ सकता है, जिनसे आप छुटकारा पाना चाहते हैं।
नोट: यह केवल एक लूप उदाहरण के भीतर एक सूची से हटाए गए आइटम को जोड़ रहा है :
तो आइए हमारी सूचियों को हमेशा की तरह परिभाषित करें
String[] names = {"James","Smith","Sonny","Huckle","Berry","Finn","Allan"};
List<String> nameList = new ArrayList<>();
//Create a List from an Array
nameList.addAll(Arrays.asList(names));
String[] removeNames = {"Sonny","Huckle","Berry"};
List<String> removeNameList = new ArrayList<>();
//Create a List from an Array
removeNameList.addAll(Arrays.asList(removeNames));
निम्न विधि हमारे में तत्वों को हटाने के जादू दो संग्रह वस्तुओं और प्रदर्शन में ले जाता है removeNameList में तत्वों के साथ उस मैच nameList ।
private static void removeNames(Collection<String> collection1, Collection<String> collection2) {
//get Iterator.
Iterator<String> iterator = collection1.iterator();
//Loop while collection has items
while(iterator.hasNext()){
if (collection2.contains(iterator.next()))
iterator.remove(); //remove the current Name or Item
}
}
विधि कॉलिंग और में गुजर nameList और removeNameList के रूप में इस प्रकार है removeNames(nameList,removeNameList);
निम्नलिखित उत्पादन का उत्पादन करेगा:
नाम हटाने से पहले एरे सूची: जेम्स स्मिथ सन्नी हकल बेरी फिन एलन
नाम हटाने के बाद एरे सूची: जेम्स स्मिथ फिन एलन
संग्रह के लिए एक सरल स्वच्छ उपयोग जो सूचियों के भीतर दोहराए जाने वाले तत्वों को हटाने के काम में आ सकता है।
Iterator या प्रत्येक-लूप के साथ उपयोग के लिए अपनी स्वयं की Iterable संरचना बनाना।
यह सुनिश्चित करने के लिए कि हमारे संग्रह को itter या for-प्रत्येक लूप का उपयोग करके पुनरावृत्त किया जा सकता है, हमें निम्नलिखित चरणों का ध्यान रखना होगा:
- हम जिस सामान पर
Iterableचाहते हैं, उसेIterableहोनाIterableऔरIterableiterator()उजागर करना होगा। -
hasNext(),next()औरremove()को ओवरराइड करकेjava.util.Iteratorडिज़ाइन करें।
मैंने नीचे एक साधारण जेनेरिक लिंक्ड सूची कार्यान्वयन जोड़ा है, जो उपरोक्त सूची का उपयोग करता है ताकि लिंक की गई सूची को चलने योग्य बनाया जा सके।
package org.algorithms.linkedlist;
import java.util.Iterator;
import java.util.NoSuchElementException;
public class LinkedList<T> implements Iterable<T> {
Node<T> head, current;
private static class Node<T> {
T data;
Node<T> next;
Node(T data) {
this.data = data;
}
}
public LinkedList(T data) {
head = new Node<>(data);
}
public Iterator<T> iterator() {
return new LinkedListIterator();
}
private class LinkedListIterator implements Iterator<T> {
Node<T> node = head;
@Override
public boolean hasNext() {
return node != null;
}
@Override
public T next() {
if (!hasNext())
throw new NoSuchElementException();
Node<T> prevNode = node;
node = node.next;
return prevNode.data;
}
@Override
public void remove() {
throw new UnsupportedOperationException("Removal logic not implemented.");
}
}
public void add(T data) {
Node current = head;
while (current.next != null)
current = current.next;
current.next = new Node<>(data);
}
}
class App {
public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<>(1);
list.add(2);
list.add(4);
list.add(3);
//Test #1
System.out.println("using Iterator:");
Iterator<Integer> itr = list.iterator();
while (itr.hasNext()) {
Integer i = itr.next();
System.out.print(i + " ");
}
//Test #2
System.out.println("\n\nusing for-each:");
for (Integer data : list) {
System.out.print(data + " ");
}
}
}
उत्पादन
using Iterator:
1 2 4 3
using for-each:
1 2 4 3
यह जावा 7+ में चलेगा। आप इसे जावा 5 और जावा 6 पर भी प्रतिस्थापित करके बना सकते हैं:
LinkedList<Integer> list = new LinkedList<>(1);
साथ में
LinkedList<Integer> list = new LinkedList<Integer>(1);
या संगत परिवर्तनों को शामिल करके किसी अन्य संस्करण को।
नुकसान: समवर्ती संशोधन अपवाद
यह अपवाद तब होता है जब एक संग्रह संशोधित किया जाता है, जबकि इटर्चर ऑब्जेक्ट द्वारा प्रदान किए गए तरीकों के अलावा अन्य तरीकों का उपयोग करते हुए। उदाहरण के लिए, हमारे पास टोपी की एक सूची है और हम उन सभी को हटाना चाहते हैं जिनके कान फड़फड़ाने हैं:
List<IHat> hats = new ArrayList<>();
hats.add(new Ushanka()); // that one has ear flaps
hats.add(new Fedora());
hats.add(new Sombrero());
for (IHat hat : hats) {
if (hat.hasEarFlaps()) {
hats.remove(hat);
}
}
यदि हम इस कोड को चलाते हैं, तो समसामयिकीकरण अपवाद को उठाया जाएगा क्योंकि कोड इसे पुनरावृत्त करते हुए संग्रह को संशोधित करता है। यदि एक ही सूची के साथ काम करने वाले कई थ्रेड्स में से कोई एक संग्रह को संशोधित करने का प्रयास कर रहा है तो वही अपवाद हो सकता है जबकि अन्य उस पर पुनरावृति करते हैं। कई थ्रेड्स में संग्रह का समवर्ती संशोधन एक स्वाभाविक बात है, लेकिन समवर्ती प्रोग्रामिंग टूलबॉक्स से सामान्य उपकरणों के साथ इलाज किया जाना चाहिए जैसे कि सिंक्रनाइज़ेशन ताले, समवर्ती संशोधन के लिए अपनाए गए विशेष संग्रह, प्रारंभिक से क्लोन संग्रह को संशोधित करना आदि।
उप संग्रह
सूची उप सूची (int fromIndex, intIndex)
यहाँ से Indexex समावेशी है और Indexex अनन्य है।
List list = new ArrayList();
List list1 = list.subList(fromIndex,toIndex);
- यदि सूची सीमा में मौजूद नहीं है, तो यह IndexOutofBoundException को फेंकता है।
- सूची 1 पर कभी भी किए गए परिवर्तन सूची में समान परिवर्तनों को प्रभावित करेंगे। इसे समर्थित संग्रह कहा जाता है।
- अगर fromnIndex toIndex (fromIndex> toIndex) से अधिक है तो यह IllegalArgumentException को फेंकता है।
उदाहरण:
List<String> list = new ArrayList<String>();
List<String> list = new ArrayList<String>();
list.add("Hello1");
list.add("Hello2");
System.out.println("Before Sublist "+list);
List<String> list2 = list.subList(0, 1);
list2.add("Hello3");
System.out.println("After sublist changes "+list);
आउटपुट:
Sublist से पहले [Hello1, Hello2]
सबलिस्ट परिवर्तन के बाद [Hello1, Hello3, Hello2]
सेट सबसेट (fromIndex, toIndex)
यहाँ से Indexex समावेशी है और Indexex अनन्य है।
Set set = new TreeSet();
Set set1 = set.subSet(fromIndex,toIndex);
लौटा सेट अपनी श्रेणी के बाहर एक तत्व सम्मिलित करने के प्रयास पर IllegalArgumentException को फेंक देगा।
मानचित्र उप-मानचित्र (fromKey, toKey)
fromKey समावेशी है और toKey अनन्य है
Map map = new TreeMap();
Map map1 = map.get(fromKey,toKey);
यदि काकी कीके की तुलना में अधिक है या यदि इस नक्शे में स्वयं एक प्रतिबंधित सीमा है, और केकेई या टोके सीमा के सीमा के बाहर है, तो यह IllegalArgumentException फेंकता है।
सभी संग्रह समर्थित संग्रह का अर्थ है कि उप संग्रह पर किए गए परिवर्तन मुख्य संग्रह पर समान परिवर्तन होंगे।